使用 R expss 和 data.table 是否可以从 csv 文件加载 data.table 标签而不是手动输入代码?
Using R expss and data.table is it possible to load data.table labels from a csv file instead of typing the code in by hand?
应用标签是在报告时使调查数据易于理解的重要部分
所以我能找到的最好的例子是 expss::apply_labels()
例如著名的 mtcars 示例 https://cran.r-project.org/web/packages/expss/vignettes/tables-with-labels.html
作为输入,这需要一个 data.table 和一个逗号分隔的赋值对列表,例如
apply_labels(dt, col1 = "label1", col2 = "label2", col3 = "label3")
如果您有一个数据文件和几列并且每次都输入它们很麻烦,这很好,但是如果您有很多数据文件,这就不是很有用了。那么如何加载一个 csv 元数据文件呢?
格式:
第 1 列第 2 列第 3 列
标签 1 标签 2 标签 3
Col 名称与数据中的相同名称匹配 table
这意味着有效地翻译元数据 csv 文件,以便它生成
coln = "labeln"
每列。
到目前为止,我发现最大的问题是应用标签列名称是对象而不是字符串,很难将字符串转换为正确范围内的对象。
这是我要去的地方
library(expss)
library(data.table)
library(glue)
readcsvdata <- function(dfile)
{
rdata <- fread(file = dfile, sep = "," , quote = "\"" , header = TRUE,
stringsAsFactors = FALSE, na.strings = getOption("datatable.na.strings","NA"))
return(rdata)
}
rawdatafilename <- "testdata.csv"
rawmetadata <- "metadata.csv"
mdt <- readcsvdata(rawmetadata)
rdt <-readcsvdata(rawdatafilename)
commonnames <- intersect(names(mdt),names(rdt)) # find common
qlabels <- as.character(mdt[1, commonnames, with = FALSE])
comslist <- list()
for (i in 1:length(commonnames)) # loop through commonnames and qlabels
{
if (i == length(commonnames))
{x <- glue('{commonnames[i]} = "{qlabels[i]}"')} # no comma for final item
else
{x <- glue('{commonnames[i]} = "{qlabels[i]}",')} # comma for next item
comslist[[i]] <- x
}
comstring <- paste(unlist(comslist), collapse = '')
tdt = apply_labels(tdt, eval(parse(text = comstring)))
产生
解析错误(text = comstring): :1:24: 意外的 ',' 1: varone = "Label1", ^
oh 和 print(comstring) 产生:
[1] "varone = \"Question one\",vartwo = \"Question two\",varthree =
\"Question three\",varfour = \"Question four\",varfive = \"Question
five\",varsix = \"Question six\",varseven = \"Question
seven\",vareight = \"Question eight\",varnine = \"Question
nine\",varten = \"Question ten\""
我手边没有 expss
,但我认为这是关于如何在 R 中以编程方式分配函数参数的一般性内容。
如果您从包含您需要的三个配对的 CSV 文件开始,
csvdat <- read.csv(stringsAsFactors=FALSE, text="
col1,col2,col3
label1,label2,label3")
我将编写一个假函数(因为我没有 expss
,而且它并不重要)它动态地接受第一个参数和零个或多个后续参数。
my_fake_labels <- function(x, ...) {
dots <- list(...)
message("x labels : ", paste(sQuote(colnames(x)), collapse = ", "))
message("other names: ", paste(sQuote(names(dots)), collapse = ", "))
}
origDT <- data.table(aa=1, bb=2)
my_fake_labels(origDT, col1="label1", col2="label2", col3="label3")
# x labels : 'aa', 'bb'
# other names: 'col1', 'col2', 'col3'
这是您要避免的手动参数设置。 (我知道我在这里没有做任何标签设置,让我们暂时忽略它。)
执行此操作的编程方式,使用 origDT
作为第一个参数,csvdat
的元素作为第二个和后续参数:
do.call(my_fake_labels, c(list(origDT), csvdat))
# x labels : 'aa', 'bb'
# other names: 'col1', 'col2', 'col3'
do.call
的第二个参数需要是 list
,可选命名。由于 data.frame
(因此 data.table
)只是一个美化的名字 list
,这符合要求。它所做的是获取列表中的每个元素并将其应用为函数的相应参数(do.call
的第一个参数)。
list(origDT)
是因为通常 c(...)
函数会连接两个列表的 columns/elements。如果我们只执行 c(origDT, csvdat)
,那么将使用 ncol(origDT) + ncol(csvdat)
个参数调用该函数,而不是所需的 1 + ncol(csvdat)
。为此,c(list(origDT), ...)
确保整个 origDT
是函数的第一个参数。
(以编程方式形成 csvdat
可能也很容易,而不是需要外部文件,但我猜你有理由通过 CSV 来完成。)
apply_labels
对于外部词典的赋值标签不是很方便。您可以使用 var_lab
代替:
library(expss)
library(data.table)
readcsvdata <- function(dfile)
{
rdata <- fread(file = dfile, sep = "," , quote = "\"" , header = TRUE,
stringsAsFactors = FALSE, na.strings = getOption("datatable.na.strings","NA"))
return(rdata)
}
rawdatafilename <- "testdata.csv"
rawmetadata <- "metadata.csv"
mdt <- readcsvdata(rawmetadata)
rdt <-readcsvdata(rawdatafilename)
commonnames <- intersect(names(mdt),names(rdt)) # find common
qlabels <- as.list(mdt[1, commonnames, with = FALSE])
for (each_name in commonnames) # loop through commonnames and qlabels
{
var_lab(rdt[[each_name]]) <- qlabels[[each_name]]
}
值标签有一个类似的 val_lab
函数。此外,您可能对 apply_dictionary
和 create_dictionary
函数感兴趣。要获得有关它们的帮助,请在控制台中键入 ?apply_dictionary
。
应用标签是在报告时使调查数据易于理解的重要部分
所以我能找到的最好的例子是 expss::apply_labels() 例如著名的 mtcars 示例 https://cran.r-project.org/web/packages/expss/vignettes/tables-with-labels.html
作为输入,这需要一个 data.table 和一个逗号分隔的赋值对列表,例如
apply_labels(dt, col1 = "label1", col2 = "label2", col3 = "label3")
如果您有一个数据文件和几列并且每次都输入它们很麻烦,这很好,但是如果您有很多数据文件,这就不是很有用了。那么如何加载一个 csv 元数据文件呢? 格式:
第 1 列第 2 列第 3 列
标签 1 标签 2 标签 3
Col 名称与数据中的相同名称匹配 table
这意味着有效地翻译元数据 csv 文件,以便它生成
coln = "labeln"
每列。
到目前为止,我发现最大的问题是应用标签列名称是对象而不是字符串,很难将字符串转换为正确范围内的对象。
这是我要去的地方
library(expss)
library(data.table)
library(glue)
readcsvdata <- function(dfile)
{
rdata <- fread(file = dfile, sep = "," , quote = "\"" , header = TRUE,
stringsAsFactors = FALSE, na.strings = getOption("datatable.na.strings","NA"))
return(rdata)
}
rawdatafilename <- "testdata.csv"
rawmetadata <- "metadata.csv"
mdt <- readcsvdata(rawmetadata)
rdt <-readcsvdata(rawdatafilename)
commonnames <- intersect(names(mdt),names(rdt)) # find common
qlabels <- as.character(mdt[1, commonnames, with = FALSE])
comslist <- list()
for (i in 1:length(commonnames)) # loop through commonnames and qlabels
{
if (i == length(commonnames))
{x <- glue('{commonnames[i]} = "{qlabels[i]}"')} # no comma for final item
else
{x <- glue('{commonnames[i]} = "{qlabels[i]}",')} # comma for next item
comslist[[i]] <- x
}
comstring <- paste(unlist(comslist), collapse = '')
tdt = apply_labels(tdt, eval(parse(text = comstring)))
产生
解析错误(text = comstring): :1:24: 意外的 ',' 1: varone = "Label1", ^
oh 和 print(comstring) 产生:
[1] "varone = \"Question one\",vartwo = \"Question two\",varthree = \"Question three\",varfour = \"Question four\",varfive = \"Question five\",varsix = \"Question six\",varseven = \"Question seven\",vareight = \"Question eight\",varnine = \"Question nine\",varten = \"Question ten\""
我手边没有 expss
,但我认为这是关于如何在 R 中以编程方式分配函数参数的一般性内容。
如果您从包含您需要的三个配对的 CSV 文件开始,
csvdat <- read.csv(stringsAsFactors=FALSE, text="
col1,col2,col3
label1,label2,label3")
我将编写一个假函数(因为我没有 expss
,而且它并不重要)它动态地接受第一个参数和零个或多个后续参数。
my_fake_labels <- function(x, ...) {
dots <- list(...)
message("x labels : ", paste(sQuote(colnames(x)), collapse = ", "))
message("other names: ", paste(sQuote(names(dots)), collapse = ", "))
}
origDT <- data.table(aa=1, bb=2)
my_fake_labels(origDT, col1="label1", col2="label2", col3="label3")
# x labels : 'aa', 'bb'
# other names: 'col1', 'col2', 'col3'
这是您要避免的手动参数设置。 (我知道我在这里没有做任何标签设置,让我们暂时忽略它。)
执行此操作的编程方式,使用 origDT
作为第一个参数,csvdat
的元素作为第二个和后续参数:
do.call(my_fake_labels, c(list(origDT), csvdat))
# x labels : 'aa', 'bb'
# other names: 'col1', 'col2', 'col3'
do.call
的第二个参数需要是 list
,可选命名。由于 data.frame
(因此 data.table
)只是一个美化的名字 list
,这符合要求。它所做的是获取列表中的每个元素并将其应用为函数的相应参数(do.call
的第一个参数)。
list(origDT)
是因为通常 c(...)
函数会连接两个列表的 columns/elements。如果我们只执行 c(origDT, csvdat)
,那么将使用 ncol(origDT) + ncol(csvdat)
个参数调用该函数,而不是所需的 1 + ncol(csvdat)
。为此,c(list(origDT), ...)
确保整个 origDT
是函数的第一个参数。
(以编程方式形成 csvdat
可能也很容易,而不是需要外部文件,但我猜你有理由通过 CSV 来完成。)
apply_labels
对于外部词典的赋值标签不是很方便。您可以使用 var_lab
代替:
library(expss)
library(data.table)
readcsvdata <- function(dfile)
{
rdata <- fread(file = dfile, sep = "," , quote = "\"" , header = TRUE,
stringsAsFactors = FALSE, na.strings = getOption("datatable.na.strings","NA"))
return(rdata)
}
rawdatafilename <- "testdata.csv"
rawmetadata <- "metadata.csv"
mdt <- readcsvdata(rawmetadata)
rdt <-readcsvdata(rawdatafilename)
commonnames <- intersect(names(mdt),names(rdt)) # find common
qlabels <- as.list(mdt[1, commonnames, with = FALSE])
for (each_name in commonnames) # loop through commonnames and qlabels
{
var_lab(rdt[[each_name]]) <- qlabels[[each_name]]
}
值标签有一个类似的 val_lab
函数。此外,您可能对 apply_dictionary
和 create_dictionary
函数感兴趣。要获得有关它们的帮助,请在控制台中键入 ?apply_dictionary
。