如何将列名作为输入从其他列表中传递,并将其他data.table引用到总和分数?

时间:2014-02-06 14:30:10

标签: r data.table

我有两个data.table(s)DT1和RF,其中DT1是主表,RF是变量值的人行横道。

 DT1 <- data.table(id = c(1:10),Var1=c(1,0,0,0,1,0,1,1,0,0) ,Var2=c(0,0,0,0,1,0,1,0,0,1), 
              Var3=c(1,1,1,0,0,0,1,1,0,0),Var4=c(1,1,0,0,1,0,0,0,0,0),
              Var5=c(0,0,0,0,1,0,1,1,0,0))
 RF <- data.table (Variable = c("Var1","Var2","Var3","Var4","Var5","Var6","Var7","Var8",
              "Var9","Var10"), 
              CO = c(1.1,2.3,1.4,1.5,1.0,3.8,2.5,3.7,2.1,2.0), 
              IN = c(2.1,1.3,1.9,2.5,1.7,2.8,2.9,1.7,1.1,2.0))

我想计算DT1中模型CO和IN的分数列,它是加法的,并且将两个模型的输入作为输入。为此我创建了两个模型的变量列表:

 List1 <- c("Var1","Var3","Var5")
 List2 <- c("Var1","Var2","Var6","Var7","Var8")

因此,如果我正在计算Score_CO,那么我的函数应该在List1中检查变量。与DT1中的每一行一样,它应检查是否

 1) Var1 == 1, If yes, 
 2) then check for that in RF for RF$Variable == Var1, if yes
 3) get RF$CO value, 
 4) else return (0) 

我尝试了两种方法:

 METHOD 1:
 L1<- length(List1)
 y<-0
 DT1 <-DT1[,Score_CO:={for(i in 1:L1){
             x<-parse(text = List1[i])
             if(DT1[,eval(x)] == 1){
             x<-RF[which(RF[,'Variable'] == List1[i],),CO]}
             else{as.numeric(0.0)}
             y=y+x }
             return(y)}]

 METHOD 2:
 Score_Calc<-function(DT,RF, List, model = 'CO'){
 pvar<- 0
 pvar<-for(i in 1:nrow(DT)){
 for(j in 1:length(List)){
  x<-parse(text = List[j])  
  ifelse(DT[i,eval(x)] == 1, RF[which(RF[,'Variable'] == List[j],),model], 0)
 }
 pvar <- pvar + pvar
 DT[,paste0('Score_',model):= pvar]
 }
 return(DT)
 }

 Score_Calc(DT=DT1,RF = RF, List=List1, model = 'CO')

但我没有得到结果。输出应该是:

 OUTPUT:
  id    Var1    Var2    Var3    Var4    Var5    Score_CO
   1    1   0   1   1   0   2.5
   2    0   0   1   1   0   1.4
   3    0   0   1   0   0   1.4
   4    0   0   0   0   0   0
   5    1   1   0   1   1   2.1
   6    0   0   0   0   0   0
   7    1   1   1   0   1   3.5
   8    1   0   1   0   1   3.5
   9    0   0   0   0   0   0
  10    0   1   0   0   0   0

P.S。:Score_CO = Var1 + Var2 + Var3(RF表CO列的值)

请看看并帮助我找到我做错了什么。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

这是一个矩阵乘法版本:

as.matrix(DT1[, -1, with=F]) %*% as.matrix(RF[1:5, -1, with=F])
#        CO  IN
#  [1,] 4.0 6.5
#  [2,] 2.9 4.4
#  [3,] 1.4 1.9
#  [4,] 0.0 0.0
#  [5,] 5.9 7.6
#  [6,] 0.0 0.0
#  [7,] 5.8 7.0
#  [8,] 3.5 5.7
#  [9,] 0.0 0.0
# [10,] 2.3 1.3

data.table版本1.请注意,一旦设置了RF键,矩阵乘法将为您提供不同的答案,因为设置键重新排序

编辑:执行两种计算的替代方案:

setkey(RF, Variable)
fun <- function(DT, col) sum(RF[names(DT), ][, col, with=F] * unlist(DT))
DT1[,list(CO=fun(.SD, "CO"), IN=fun(.SD, "IN")), by=id]
#     id  CO  IN
#  1:  1 4.0 6.5
#  2:  2 2.9 4.4
#  3:  3 1.4 1.9
#  4:  4 0.0 0.0
#  5:  5 5.9 7.6
#  6:  6 0.0 0.0
#  7:  7 5.8 7.0
#  8:  8 3.5 5.7
#  9:  9 0.0 0.0
# 10: 10 2.3 1.3

OLD VERSION:

这是计算CO的潜在解决方案。您可以轻松地将其扩展为IN。基本上,我们所做的是将DT1中的值乘以相应的RF值,然后添加:

setkey(RF, Variable)
DT2 <- DT1[, c(
  list(id=id),
  sapply(
    names(.SD[, -1, with=F]), 
    function(x) unlist(.SD[, x, with = F] * RF[x, ][, CO]),
    simplify=F
  )
) ][, CO:=apply(.SD[, -1, with=F], 1, sum)]
DT2
#     id Var1 Var2 Var3 Var4 Var5  CO
#  1:  1  1.1  0.0  1.4  1.5    0 4.0
#  2:  2  0.0  0.0  1.4  1.5    0 2.9
#  3:  3  0.0  0.0  1.4  0.0    0 1.4
#  4:  4  0.0  0.0  0.0  0.0    0 0.0
#  5:  5  1.1  2.3  0.0  1.5    1 5.9
#  6:  6  0.0  0.0  0.0  0.0    0 0.0
#  7:  7  1.1  2.3  1.4  0.0    1 5.8
#  8:  8  1.1  0.0  1.4  0.0    1 3.5
#  9:  9  0.0  0.0  0.0  0.0    0 0.0
# 10: 10  0.0  2.3  0.0  0.0    0 2.3

第一个sapply循环遍历数据表中的每个Var#列,找到CORF的相应值,并将该列乘以该值(这会产生您在上面看到的修改后的Var1-5值。CO:=apply(...位只计算每行Var1-5的总和,并将其保存为CODT2 }。