【发布时间】:2015-09-12 21:19:16
【问题描述】:
我有一个非常相似的数据表
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 大于val 对于相同diag 的概率,并将其分配给表格的新列,例如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 行,diag 上有一些 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.tables,我更喜欢使用该软件包的解决方案,但是我绝对愿意接受任何其他解决方案来源(plyr、dplyr 等)。
谢谢,
【问题讨论】:
-
dt[,prob2:= 1 - pnorm(val,mean(val),sd(val),lower.tail=FALSE),by=diag]或类似的东西似乎与您的结果相匹配。不知道为什么我需要做1 - pnorm。 -
结果的长度不会是 7 吗?我想要一个长度为 50 的结果,
prob计算 for each 行,只是它是通过考虑 share 相同@的所有值的分布来计算的987654335@ -
不,
by=默认为每个组中的每一行进行计算。这就是重点。 -
你的例子有几个问题。 50 比您需要的多,如果显示在答案中以显示结果,则会占用大量空间。而且您的示例是随机生成的,但您没有设置种子,因此无法重现。
-
dt[,prob2:= pnorm(val,mean(val),sd(val),lower.tail=FALSE),by=diag]现在给出了相同的结果 - 仅需要1 -是因为您使用了lower.tail=F而不是lower.tail=FALSE并且我有一个名为F的变量浮动。充分输入FALSE和TRUE的好理由。
标签: r data.table vectorization subset