使用 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_dictionarycreate_dictionary 函数感兴趣。要获得有关它们的帮助,请在控制台中键入 ?apply_dictionary