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

时间:2013-10-09 15:25:04

标签: r data.table

  

注意:我在这个问题中遇到的确切问题不适用于最新版本的数据表。如果您想执行标题中所述的操作,请查看常见问题解答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)``,我想知道......

  • 如何动态指定名称“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”的轻微烦恼,所以第一个问题仍然是部分开放。

2 个答案:

答案 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问题之外)