【问题标题】:R: Create new variables in data.table from a separate list of parametersR:从单独的参数列表在 data.table 中创建新变量
【发布时间】:2016-10-25 15:22:11
【问题描述】:

创建一个数据集和我要使用的函数

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

【问题讨论】:

  • 使用testFunction&lt;-function(x,transformation){x+(1-transformation)*shift(x, fill=0)}
  • 抱歉,投反对票,因为这样做是个坏主意(不必要地迭代并在字符串中编写代码进行评估)。
  • @ExperimenteR 我怀疑这会奏效。可能需要在某处有一个累积和或累积乘积来绕过迭代。
  • @Frank,恕我直言,没有理由否决这个 Q,因为它显示了 OP 为解决他的问题而付出的巨大努力。而且,Q 是关于如何做得更好。
  • @UweBlock 我也太宽泛了。如果将其简化为一个问题(testFunction 本身就是一个相当大的问题),那将有所帮助。我用我的 DV 作为路标,告诉那些后来偶然发现它的人“这是个坏主意”。这是一个有效的,尽管是主观的原因。如果您将鼠标悬停在向下投票箭头上,我指的是“没用”。

标签: r data.table


【解决方案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

【讨论】:

  • 有道理。唯一缺少的是将函数应用于两个不同列的能力
【解决方案2】:

感谢 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

【讨论】:

    猜你喜欢
    • 2015-10-22
    • 2022-06-15
    • 1970-01-01
    • 2013-09-23
    • 2020-11-27
    • 2021-05-14
    • 2021-12-05
    • 1970-01-01
    • 2019-09-11
    相关资源
    最近更新 更多