如果我有一个数据表,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 ::会产生这种差异。
答案 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
错误,这就是为什么我要努力再现结果......