data.table`:=`具有动态输入(现有列)和输出(新列名)的赋值表达式

Fra*_*ank 8 r data.table

注意:我在此问题中遇到的确切问题不适用于最新版本的数据表.如果你想做标题中描述的事情,请查看包FAQ中的相应问题,1.6确定,但我不提前知道这些表达式.我如何以编程方式传递它们?.

我已经看到一个答案,说明如何构建一个要进行评估的表达式

DT[,j=eval(expr)]
Run Code Online (Sandbox Code Playgroud)

我正在使用这个作业,```:=`(mycol = my_calculation)``,我想知道......

  • 如何动态分配名称"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)
Run Code Online (Sandbox Code Playgroud)

我想将设置和使用阶段分开,因此我的代码更易于维护.我的真实表达比这个例子更麻烦(它只选择一列).

问题

第一个问题:如何使分配到的列"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)
Run Code Online (Sandbox Code Playgroud)

这仍然涉及两步操作和跟踪"Vtmp"的轻微烦恼,所以第一个问题仍然是部分开放.

edd*_*ddi 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
Run Code Online (Sandbox Code Playgroud)

要回答已编辑的问题,要开始eval工作,请将其.SD用作环境:

DT[, (col_out) := eval(expr, .SD)]
Run Code Online (Sandbox Code Playgroud)

另外,请参阅此问题并在那里进行更新 - 在data.table中引用和引用


Ric*_*rta 5

最简单的方法是在评估表达式之后设置它.毕竟,执行的时间是恒定的,接近0.

someDummyVar <- "tempColName_XCWF5D"
DT [, (someDummyVar) := eval(expr) ]

setnames(DT, someDummyVar, RealColumnName)
Run Code Online (Sandbox Code Playgroud)

至于问题二:不要打开详细的警告,你不会得到详细的警告;)

options(datatable.verbose=FALSE)
Run Code Online (Sandbox Code Playgroud)

至于Reduce:尝试将其作为单独的简化问题发布,以便更容易理解您正在做的事情(eval问题之外)