具有data.table变量的函数,其名称存储在字符向量中

时间:2016-09-02 11:40:19

标签: r data.table

我不是一个大数据专家但我对某些事情感到困惑。这是我的简单例子:

test<-data.table(x= 1:10,y= 1:10,z= 1:10, l = 11:20,d= 21:30)
test<-test[,..I:=.I]
vec_of_names = c("z","l","d")

function_test<-function(x,y){
  sum(x)+y
}

vec_of_final_names<-c("sum_z","sum_l","sum_d")

当我尝试这样做时:

for (i in 1:length(vec_of_names)){
  test<-test[,vec_of_final_names[i]:=function_test(x=.SD,y=eval(parse(text=vec_of_names[i]))),.SDcols=c("x","y"),by=..I]
}

我收到错误:

 Error in eval(expr, envir, enclos) : object 'z' not found 

虽然下面的代码工作得很好,但有点丑陋而且速度慢。也许有人可以提出更好的选择。

for (i in 1:length(vec_of_names)){
  test<-test[,vec_of_final_names[i]:=function_test(x=eval(parse(text=paste("c(",paste(c("x","y"),collapse=","),")",sep=""))),y=eval(parse(text=vec_of_names[i]))),by=..I]
}

1 个答案:

答案 0 :(得分:2)

指定.SDcols并按= ..I分组后(..I是列名称的奇怪名称),我们unlist .SD,获取sum,使用list获取mget中'vec_o​​f_names'的值,使用+执行相应元素的sum(unlist(.SD))并分配(:=)用'vec_o​​f_final_names'来创建新列

test[, (vec_of_final_names) := Map(`+`, sum(unlist(.SD)), 
                    mget(vec_of_names)), by = ..I, .SDcols = x:y]

根据这个例子,这也可以在没有分组变量的情况下完成

test[, (vec_of_final_names) := Map(`+`, list(x+y), mget(vec_of_names))]

或者指定.SDcols

test[, (vec_of_final_names) := Map(`+`, list(Reduce(`+`, .SD)), 
                            mget(vec_of_names)), .SDcols = x:y]

或使用OP的功能

test[, (vec_of_final_names) := Map(function_test, list(unlist(.SD)), 
                mget(vec_of_names)), ..I, .SDcols = x:y]
test
#      x  y  z  l  d ..I sum_z sum_l sum_d
# 1:  1  1  1 11 21   1     3    13    23
# 2:  2  2  2 12 22   2     6    16    26
# 3:  3  3  3 13 23   3     9    19    29
# 4:  4  4  4 14 24   4    12    22    32
# 5:  5  5  5 15 25   5    15    25    35
# 6:  6  6  6 16 26   6    18    28    38
# 7:  7  7  7 17 27   7    21    31    41
# 8:  8  8  8 18 28   8    24    34    44
# 9:  9  9  9 19 29   9    27    37    47
#10: 10 10 10 20 30  10    30    40    50