我有两个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列的值)
请看看并帮助我找到我做错了什么。任何帮助表示赞赏。
答案 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#
列,找到CO
中RF
的相应值,并将该列乘以该值(这会产生您在上面看到的修改后的Var1-5
值。CO:=apply(...
位只计算每行Var1-5
的总和,并将其保存为CO
列DT2
}。