通过保存在变量中的名称引用data.table列

时间:2013-05-17 20:17:42

标签: r data.table

data.table是一个很棒的R包,我在我正在开发的库中使用它。到目前为止,一切都很顺利,除了一个并发症。使用保存在变量中的名称来引用data.table列似乎要困难得多(与传统数据帧相比)(对于数据帧,例如:colname="col"; df[df[,colname]<5,colname]=0)。

也许最让事情变得复杂的是data.table中明显缺乏语法一致性。在某些情况下,eval(colname)get(colname),甚至c(colname)似乎都有效。在其他人中,DT[,colname, with=F]是解决方案。然而在其他方面,例如set()subset()函数,我根本没有找到解决方案。最后,一个极端的,虽然也很常见的用例在前面讨论过(passing column names to data.table programmatically),虽然显然做了他们自己的工作,所提出的解决方案似乎并不特别可读......

也许我太复杂了?如果有人可以记下快速备忘单,以便使用不同常见场景的变量来引用data.table列名称,我将非常感激。

更新

提供的一些具体示例我可以对列名进行硬编码:

x.short = subset(x, abs(dist)<=100)
set(x, which(x$val<10), "val", 0) 

现在假设distcol="dist"valcol="val"。使用distcolvalcol而不是distval进行上述操作的最佳方法是什么?

4 个答案:

答案 0 :(得分:22)

如果您要在j表达式中执行复杂的操作,则应该使用evalquote。当前版本的data.table中存在的一个问题是,eval的环境并不总是正确处理 - eval and quote in data.table(注意:根据对更新的更新,对该答案进行了更新包。) - 目前的修复方法是将.SD添加到eval。据我所知,一些测试表明我运行此操作不会影响速度(例如.SD[1]j的方式。)

有趣的是,这个问题只会影响j,您可以在eval中使用i,但.SD无法使用{。}}。

另一个问题是分配,你必须有字符串。我知道一种从引​​用的表达式中提取字符串名称的方法 - 它不漂亮,但它有效。以下是将所有内容组合在一起的示例:

x = data.table(dist = c(1:10), val = c(1:10))
distcol = quote(dist)
valcol = quote(val)

x[eval(valcol) < 5,
  capture.output(str(distcol, give.head = F)) := eval(distcol)*sum(eval(distcol, .SD))]

请注意我没有在.SD中添加eval(distcol),但如果我将其从另一个eval中删除则不会。

另一种选择是使用get

diststr = "dist"
valstr = "val"

x[get(valstr) < 5, c(diststr) := get(diststr)*sum(get(diststr))]

答案 1 :(得分:7)

也许您已经知道这个解决方案了吗?

DT[[colname]]

这是受@ eddi在以下评论中的解决方案的启发,使用OP的例子:

set.seed(1)
x = data.table(a = 1:10, b=rnorm(10))
colstr="b"
col <- eval(parse(text=paste("quote(",colstr,")",sep="")))
x[eval(col)<0]
x[eval(col)<0,c(colstr):=-100]

答案 2 :(得分:3)

假设您在变量x中有列名,您可以

colname = as.name(x)

然后,您可以在colname函数

中使用subset

答案 3 :(得分:1)

绝对不建议使用

eval来使用动态保存的变量对data.table进行子集化。以下示例将有所帮助:

# Toy data.table example
DT = data.table(a = c(1,2,3), b = c(4,5,6))

# Saved variable
mVar <- "a"

# Subset
DT[DT[[mVar]] < 2]

eval对复杂的字符表达式非常敏感,通常不建议将其用于生产代码。