R:从单独的参数列表中创建data.table中的新变量

时间:2016-10-25 15:22:12

标签: r data.table

创建数据集和我想要使用的功能

library(data.table)
DT <- data.table(V1=c(rep("A",5),rep("B",5)),
                 V2=rep(1:5,2),
                 V3=c(10,10,0,0,0,5,10,0,0,0),
                 V4=c(0,0,0,2,2,0,0,0,4,4))
testFunction<-function(x,transformation){
  l<-length(x)
  out <- rep(0, l)
  out[1] <- x[1]
  for (i in 2:l) {
    #out[i] <- x[i] + (1 - transformation) * x[i - 1] #EDIT: Function was wrong
    out[i] <- x[i] + (1 - transformation) * out[i - 1]
  }
  return(out)
}

现在我要做的是使用以下应用程序data.frame

中的信息创建一个新数据集newDT
application<-data.frame(var=c("V3","V3","V4"),
                        transform=c(0.5,0.9,0.5))

我想从这个函数得到的代码如下:使用应用程序中的变量名称和转换创建新变量,并通过列V1执行此操作。

newDT<-DT[,':='(V3_0.5=testFunction(V3,0.5),
         V3_0.9=testFunction(V3,0.9),
         V4_0.5=testFunction(V4,0.5)),
   by="V1"]

使用几个粘贴函数将其编码为文本,然后将其传递给eval(parse(text = ....))很简单:

application$code<-paste(application$var,"_",application$transform,"=testFunction(",application$var,",",application$transform,")",sep="")
code<-paste("newDT<-DT[,':='(",paste(application$code,collapse=","),"),by='V1']")
eval(parse(text=code))

然而,当您在字符串中传递超过4076个字符时会遇到问题((a)不知道为什么而且(b)不建议在整个Runiverse中使用。)

问题:我该如何解决这个问题?

如果速度不受影响,很高兴看到替代解决方案,例如dplyr。

编辑:输出表应如下所示

     V1 V2 V3 V4  V3_0.5  V3_0.9 V4_0.5
 1:  A  1 10  0 10.0000 10.0000      0
 2:  A  2 10  0 15.0000 11.0000      0
 3:  A  3  0  0  7.5000  1.1000      0
 4:  A  4  0  2  3.7500  0.1100      2
 5:  A  5  0  2  1.8750  0.0110      3
 6:  B  1  5  0  5.0000  5.0000      0
 7:  B  2 10  0 12.5000 10.5000      0
 8:  B  3  0  0  6.2500  1.0500      0
 9:  B  4  0  4  3.1250  0.1050      4
10:  B  5  0  4  1.5625  0.0105      6

2 个答案:

答案 0 :(得分:1)

在您的问题的核心,您可以将参数向量传递给lapply,然后通过引用创建新列,如下所示:

library(data.table)

DT <- data.table(col = 1:5)
expon <-  function(y,x){x ^ y}
params <- c(1,5,3)

DT[, (paste0("col_",params, sep = "")) := lapply(params, expon, col)]

这会给你:

   col col_1 col_5 col_3
1:   1     1     1     1
2:   2     2    32     8
3:   3     3   243    27
4:   4     4  1024    64
5:   5     5  3125   125

答案 1 :(得分:0)

感谢Chris为我提供了一个正确方向的步骤,并提供了一个可以使用单个列的解决方案。

要扩展到多个列:

#Turn application into a list
applic_list<-unlist(apply(application, 1, list), recursive = FALSE)
#lapply through this list, using .SD to call the column in question
DT[,(paste(application$var,application$transform,sep="_")) :=
    lapply(applic_list,function(y)      {
      testFunction(as.numeric(y[["transform"]]),.SD[[y[["var"]]]])
    }),by="V1"]

返回

    V1 V2 V3 V4  V3_0.5  V3_0.9 V4_0.5
 1:  A  1 10  0 10.0000 10.0000      0
 2:  A  2 10  0 15.0000 11.0000      0
 3:  A  3  0  0  7.5000  1.1000      0
 4:  A  4  0  2  3.7500  0.1100      2
 5:  A  5  0  2  1.8750  0.0110      3
 6:  B  1  5  0  5.0000  5.0000      0
 7:  B  2 10  0 12.5000 10.5000      0
 8:  B  3  0  0  6.2500  1.0500      0
 9:  B  4  0  4  3.1250  0.1050      4
10:  B  5  0  4  1.5625  0.0105      6