我有一个数据表格,类似于以下内容:
set.seed(1)
dt<-data.table(med=sample(letters,50,T),
diag=sample(LETTERS[1:7],50,T),
val=sample(1:100,50,F))
我希望计算任何
val
在相同diag
中大于val
的概率,并将其分配给表的新列,例如prob
(我知道概率不一定是正常的。我可以接受这种情况)。我可以使用for循环来完成:
for (i in 1:50){
dg<-dt[i,diag]
vl<-dt[i,val]
dt$prob[i]<-pnorm(vl,
mean(dt[diag==dg,val]),
sd(dt[diag==dg,val]),
lower.tail = F)
}
但是我的数据相当大(dt大约有800k行,对角线上有一些2k级别的数据),因此我想矢量化而不是循环。
我尝试过
dt[,
.(lapply(.SD,function(x)
pnorm(x[1],
mean(x),
sd(x),
lower.tail = F))),
by=diag,
.SDcols="val"]
当然,按diag
分组只会产生一个概率,因此没有什么用处。我也尝试过
dt[,
.(lapply(.SD,function(x)
pnorm(x[1],
mean(x),
sd(x),
lower.tail = F))),
by=.EACHI,
.SDcols="val"]
但是它会产生一个错误:
Error in `[.data.table`(dt, , .(lapply(.SD, function(x) pnorm(x[1], mean(x), :
logicial error. i is not data.table, but mult='all' and 'by'=.EACHI
如何通过向量化生成所需结果的代码?
由于我正在逐渐熟悉 data.table
,因此我更喜欢使用该包的解决方案,但我完全可以接受其他解决方案(plyr、dplyr等)。
谢谢。
dt[,prob2:= 1 - pnorm(val,mean(val),sd(val),lower.tail=FALSE),by=diag]
或类似的语句可以匹配您的结果。不确定为什么需要执行1 - pnorm
操作。 - thelatemailprob
,只是它是通过考虑所有共享相同diag
值的所有值的分布来计算的。 - PavoDiveby=
默认会对每个组中的每一行进行计算。这就是整个操作的意义所在。 - thelatemaildt[,prob2:= pnorm(val,mean(val),sd(val),lower.tail=FALSE),by=diag]
会得到相同的结果 - 只有在您使用了lower.tail=F
而不是lower.tail=FALSE
并且我有一个名为F
的变量时,才需要1-
。全写出FALSE
和TRUE
是一个好习惯。 - thelatemail