注意:我在这个问题中遇到的确切问题不适用于最新版本的数据表。如果您想执行标题中所述的操作,请查看常见问题解答1.6 OK, but I don’t know the expressions in advance. How do I programatically pass them in?中的相应问题。
我见过an answer,说明了如何在
中构建要计算的表达式DT[,j=eval(expr)]
我正在使用这个作业,```:=`(mycol = my_calculation)``,我想知道......
“动态”,我的意思是“在我为expr
编写代码后确定”。
编辑:为了更好地说明问题,这里有不同的例子。查看编辑历史记录以查看原始文件。
require(data.table)
require(plyr)
options(datatable.verbose=TRUE)
DT <- CJ(a=0:1,b=0:1,y=2)
# setup:
expr <- as.quoted(paste(expression(get(col_in_one)+get(col_in_two))))[[1]]
# usage:
col_in_one <- 'a'
col_in_two <- 'b'
col_out <- 'bah'
DT[,(col_out):=eval(expr)] # fails, should take the form j=eval(expr)
我想将设置和使用阶段分开,因此我的代码更易于维护。我的真实表达比这个例子更麻烦(它只选择一列)。
第一个问题:如何使分配到的列“col_out”动态化?我的意思是:我想动态指定“cols_in_ *”和“col_out”。
我尝试在“expr”中创建各种表达式,但as.quoted
引发了一个错误,即不将某些内容放在=
符号的左侧。
第二个问题:如何避免使用
get
的警告?
警告建议使用.SDcols
,让[.data.table
知道我正在使用哪些列。但是,如果我使用.SDcols
参数,另一个警告说,除非使用.SD
,否则没有必要这样做。
我到目前为止的解决方案是......
# Ricardo + eddi:
expr2 <- as.quoted(paste(expression(`:=`(
Vtmp=.SD[[col_in_one]]+.SD[[col_in_two]]))))[[1]]
# usage
col_in_one <- 'a'
col_in_two <- 'b'
col_out <- 'bah'
DT[,eval(expr2),.SDcols=c(col_in_one,col_in_two)]
setnames(DT,'Vtmp',col_out)
这仍然涉及两步操作和跟踪“Vtmp”的轻微烦恼,所以第一个问题仍然是部分开放。
答案 0 :(得分:8)
也许我不太了解这个问题,但这样就足够了:
DT[, (col_out) := .SD[[col_in_one]]+.SD[[col_in_two]],
.SDcols = c(col_in_one,col_in_two)]
DT
# a b y bah
#1: 0 0 2 0
#2: 0 1 2 1
#3: 1 0 2 1
#4: 1 1 2 2
要回答已修改的问题,要使eval
正常工作,请使用.SD
作为环境:
DT[, (col_out) := eval(expr, .SD)]
此外,请参阅此问题及其中的更新 - eval and quote in data.table
答案 1 :(得分:5)
最简单的方法是在评估表达式之后设置它。毕竟,执行的时间是恒定的,接近0。
someDummyVar <- "tempColName_XCWF5D"
DT [, (someDummyVar) := eval(expr) ]
setnames(DT, someDummyVar, RealColumnName)
关于问题二:不要打开详细的警告,你不会得到详细的警告;)
options(datatable.verbose=FALSE)
至于Reduce
:尝试将其作为单独的简化问题发布,以便更容易理解您正在做的事情(eval
问题之外)