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
答案 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))]
我想知道怎么做,不过......