以编程方式生成要使用`:=`语法分配给data.table的列的列表

时间:2015-05-17 19:41:42

标签: r data.table

data.table中,我可以使用`:=`语法生成立即分配给表的新列的列表,如下所示:

x <- data.table(x1=1:5, x2=1:5)
x[, `:=` (x3=x1+2, x4=x2*3)]

或者,我本可以做到以下几点:

x[, c("x3","x4") := list(x1+2, x2*3)]

我想做第一种方法,但是使用自定义函数自动构建赋值语句的右侧。例如,假设我想要一个接受一组列名的函数,然后生成新列,这些列是给定列的平均值,列名等于原始列加上一些后缀。例如,

x[, `:=` MEAN(x1,x2)]

会产生与

相同的结果
x[, `:=` (x1_mean=mean(x1), x2_mean=mean(x2))]

这可能在data.table吗?我意识到如果我愿意传递一个列名列表,例如在c("x3","x4") := ...示例中,这是可能的,但我想避免这种情况,所以我不必编写尽可能多的代码。

1 个答案:

答案 0 :(得分:1)

只需按名称参考该功能:

myfun <- "mean"
x[,paste(names(x),myfun,sep="_"):=lapply(.SD,myfun)]
#    x1 x2 x1_mean x2_mean
# 1:  1  1       3       3
# 2:  2  2       3       3
# 3:  3  3       3       3
# 4:  4  4       3       3
# 5:  5  5       3       3

自定义非常简单:

divby2 <- function(x) x/2 # custom function
myfun  <- "divby2"
mycols <- "x1"            # custom columns
x[,paste(mycols,myfun,sep="_"):=lapply(.SD,myfun),.SDcols=mycols]
#    x1 x2 x1_mean x2_mean x1_divby2
# 1:  1  1       3       3       0.5
# 2:  2  2       3       3       1.0
# 3:  3  3       3       3       1.5
# 4:  4  4       3       3       2.0
# 5:  5  5       3       3       2.5

我们有一天可能会使用paste(.SDcols,myfun,sep="_"):=lapply(.SD,myfun)之类的语法,但目前不支持左侧的.SDcols

制作功能。如果您希望功能执行此操作,那么

add_myfun <- function(DT,myfun,mycols){
  DT[,paste(mycols,myfun,sep="_"):=lapply(.SD,myfun),.SDcols=mycols]
}
add_myfun(x,"median","x2")

是否可以编写可在j的{​​{1}}内使用的函数?也许。但我认为这不是一个好主意。

  1. 您是否可以确定您的功能对DT[i,j]的所有其他用途(如j)是否健全?
  2. 您的功能是否可以利用by的优化(例如,data.table)?
  3. 其他人是否能够阅读您的代码?
  4. 使用mean可能会很慢。如果您要为许多列执行此操作,最好初始化新列并使用[进行分配。