以编程方式定义多个新data.table列的首选方法是什么?

时间:2017-02-21 13:01:33

标签: r data.table

FAQ指出在编程时向data.table添加新列的首选方法是使用quote()然后使用eval()。但是,如果我想一次添加多个列呢?玩弄这个我想出了以下解决方案:

n

产生所需的结果:

library(data.table)
DT <- data.table(V1=1:1000,
                 V2=2001:3000)
col.names <- c("V3","V4")
col.specs <- vector("list",2)
col.specs[[1]] <- quote(V1**2)
col.specs[[2]] <- quote((V1+V2)/2)

DT[,c(col.names) := lapply(col.specs,eval,envir=DT)]

我的问题很简单:这是首选方法吗?具体来说,有人可以想办法避免在lapply()调用中指定环境吗?如果我把它留下来,我得到:

> head(DT)
   V1   V2 V3   V4
1:  1 2001  1 1001
2:  2 2002  4 1002
3:  3 2003  9 1003
4:  4 2004 16 1004
5:  5 2005 25 1005
6:  6 2006 36 1006

这可能没什么大不了的,但至少对我而言,数据表无法识别自己的列感觉有点怀疑。此外,如果我逐个添加列,则无需指定环境:

> DT[,c(col.names) := lapply(col.specs,eval)]
Error in eval(expr, envir, enclos) : object 'V1' not found

1 个答案:

答案 0 :(得分:1)

单引号表达式使事情变得更容易......

library(data.table)
DT <- data.table(V1=1:1000, V2=2001:3000)

new_cols = list(
  V3 = quote(V1**2),
  v4 = quote((V1+V2)/2)
)

e = as.call(c(quote(`:=`), new_cols))
DT[, eval(e)]

然后,您可以随意添加或编辑new_cols,其名称与exprs非常接近。

来源Arun和我citing him before

旁注。上面的语法是

`:=`(col = v, col2 = v2, ...)

但我们也应该能够做到

c("col", "col2") := list(v, v2)
# aka
`:=`(c("col", "col2"), list(v, v2))

但是,我无法弄清楚如何做到这一点:

DT <- data.table(V1=1:1000, V2=2001:3000)
e2 = as.expression(list(quote(`:=`), names(new_cols), unname(new_cols)))
# gives an error:
DT[, eval(e2)]

# even though it works when written directly:
DT2[, `:=`(c("V3", "v4"), list(V1^2, (V1 + V2)/2))]

我想知道怎么做,不过......