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

msp*_*msp 41 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()功能,我根本没有找到解决方案.最后,前面讨论了一个极端的,虽然也是非常常见的用例(以编程方式将列名称传递给data.table),并且建议的解决方案虽然显然正在完成他们的工作,但似乎并不特别可读......

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

更新:

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

x.short = subset(x, abs(dist)<=100)
set(x, which(x$val<10), "val", 0) 
Run Code Online (Sandbox Code Playgroud)

现在假设distcol="dist",valcol="val".使用distcoland valcol,但不是distval?的最佳方法是什么?

edd*_*ddi 26

如果你要在j表达式中进行复杂的操作,你应该使用evalquote.当前版本的一个问题data.table是环境eval并不总是正确处理 - 在data.table中引用eval和引用(注意:根据对软件包的更新,对该答案进行了更新.) - 以及当前版本修补程序是添加.SDeval.据我所知,从一些测试我已经运行这不会影响速度(例如.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))]
Run Code Online (Sandbox Code Playgroud)

注意我是如何不添加.SD一个eval(distcol),但如果我从另一个中取出它将不会eval.

另一种选择是使用get:

diststr = "dist"
valstr = "val"

x[get(valstr) < 5, c(diststr) := get(diststr)*sum(get(diststr))]
Run Code Online (Sandbox Code Playgroud)


Fra*_*ank 7

也许你已经知道这个解决方案?

DT[[colname]]
Run Code Online (Sandbox Code Playgroud)

这是受@ 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]
Run Code Online (Sandbox Code Playgroud)

  • @msp为`j`的诀窍是将`.SD`添加到`eval` - http://stackoverflow.com/questions/15913832/eval-and-quote-in-data-table所以你可以像`` distcol = quote(dist); x [,abs(eval(distcol,.SD))<= 100]`; 对于你的例子中的`i`它应该正常工作 - `valcol = quote(val); x [eval(valcol)<10,val:= 0]` (2认同)
  • 从上面我也应该清楚,如果你要进行复杂的操作,我认为你应该使用`quote`的名字而不是字符串(你可以通过字符串来获取简单的东西,但它会变得越来越困难表达更复杂) (2认同)
  • 我喜欢转换为引用的表达式:) (2认同)