R数据表按名称访问列

时间:2014-09-10 22:56:04

标签: r data.table

如果我有一个数据表,foo,在R中有一个名为“date”的列,我可以通过符号获取日期值的向量

foo[, date]

(与数据框架不同,日期不需要在引号中)。

如何以编程方式完成?也就是说,如果我有一个变量x,其值是字符串“date”,那么如何使用该名称访问foo列?

某种有效的方法是创建一个符号:

sym <- as.name(x)
v <- foo[, eval(sym)]

...

正如我所说,这种作品,但有一些不太正确的事情。如果该代码在myPackage包中的函数myFun中,那么如果我通过以下方式显式使用该包,它似乎不起作用:

myPackage::myFun(...)

我收到一条错误消息,提示“未选择未定义的列”。

[编辑]更多细节

假设我创建了一个名为myPackage的包。该软件包有一个文件,其中包含以下内容:

library(data.table)
#' export
myFun <- function(table1) {
    names1 <- names(table1)
    name1 <- names1[[1]]
    sym <- as.Name(name1)
    table1[, eval(sym)]
}

如果我使用R Studio加载该功能,那么

myFun(tbl)

返回数据表tbl的第一列。

另一方面,如果我打电话

myPackage::myFun(tbl)

它不起作用。它抱怨

Error in .subset(x, j) : invalid subscript type 'builtin'

我只是好奇为什么myPackage ::会产生这种差异。

2 个答案:

答案 0 :(得分:1)

指出更长路的快速方法是:

subset(foo, TRUE, date)

subset函数接受其“子集”和“选择”参数的不带引号的符号/名称。 (但是,它的作者认为这是一个坏主意,并建议我们使用公式代替。)这是Hadley Wickham的高级编程网页(和书)的部分跳出的地方:http://adv-r.had.co.nz/Computing-on-the-language.html和{{3} }。您还可以查看subset.data.frame的代码:

> subset.data.frame
function (x, subset, select, drop = FALSE, ...) 
{
    r <- if (missing(subset)) 
        rep_len(TRUE, nrow(x))
    else {
        e <- substitute(subset)
        r <- eval(e, x, parent.frame())
        if (!is.logical(r)) 
            stop("'subset' must be logical")
        r & !is.na(r)
    }
    vars <- if (missing(select)) 
        TRUE
    else {
        nl <- as.list(seq_along(x))
        names(nl) <- names(x)
        eval(substitute(select), nl, parent.frame())
    }
    x[r, vars, drop = drop]
}

使用传递给函数的“裸”表达式的问题是它们的评估框架有时不符合预期。与其他函数一样,R公式带有指向它们所在环境的指针。

答案 1 :(得分:1)

我认为问题在于您已在全球环境中定义myFun,因此它似乎只能起作用。

我将as.Name更改为as.name,并创建了包含以下功能的包:

library(data.table)
myFun <- function(table1) {
    names1 <- names(table1)
    name1 <- names1[[1]]
    sym <- as.name(name1)
    table1[, eval(sym)]
}
myFun_mod <- function(dt) {
    # dt[, eval(as.name(colnames(dt)[1]))]
    dt[[colnames(dt)[1]]]
}

然后,我用它测试了它:

library(data.table)
myDt <- data.table(a=letters[1:3],b=1:3)
myFun(myDt)
myFun_mod(myDt)

myFun没有用 myFun_mod确实有效

输出:

> library(test)
> myFun(myDt)
Error in eval(expr, envir, enclos) : object 'a' not found
> myFun_mod(myDt)
[1] "a" "b" "c"

然后我将以下行添加到NAMESPACE文件中: import(data.table)

这是@mnel用这个链接谈论的内容: Using data.table package inside my own package

添加import(data.table)后,两个功能都有效。

我仍然不确定你为什么会遇到特定的.subset错误,这就是为什么我要努力再现结果......