【发布时间】:2015-10-16 10:34:46
【问题描述】:
我有两个data.tables:一个实验数据表x和一个类别查找表dict。
library(data.table)
set.seed(123)
x = data.table(samp=c(1,1,2,3,3,3,4,5,5,5,6,7,7,7,8,9,9,10,10), y=rnorm(19))
x
samp y
#1: 1 -0.56047565
#2: 1 -0.23017749
#3: 2 1.55870831
#4: 3 0.07050839
#5: 3 0.12928774
#6: 3 1.71506499
#7: 4 0.46091621
#8: 5 -1.26506123
#9: 5 -0.68685285
#10: 5 -0.44566197
#11: 6 1.22408180
#12: 7 0.35981383
#13: 7 0.40077145
#14: 7 0.11068272
#15: 8 -0.55584113
#16: 9 1.78691314
#17: 9 0.49785048
#18: 10 -1.96661716
#19: 10 0.70135590
dict = data.table(samp=c(1:5, 4:8, 7:10), cat=c(rep(1,length(1:5)), rep(2,length(4:8)), rep(3,length(7:10))))
dict
# samp cat
# 1: 1 1
# 2: 2 1
# 3: 3 1
# 4: 4 1
# 5: 5 1
# 6: 4 2
# 7: 5 2
# 8: 6 2
# 9: 7 2
# 10: 8 2
# 11: 7 3
# 12: 8 3
# 13: 9 3
# 14: 10 3
对于每个samp,我需要首先计算与之关联的所有y 的乘积。然后,我需要根据dict$cat 中指定的每个样本类别计算这些产品的总和。请注意,每个samp 映射到多个dict$cat。
这样做的一种方法是立即合并 x 和 dict,允许行重复 (allow.cartesian=T):
setkey(dict, samp)
setkey(x, samp)
step0 = dict[x, allow.cartesian=T]
setkey(step0, samp, cat)
step1 = step0[, list(prodY=prod(y)[1], cat=cat[1]), by=c("samp", "cat")]
resMet1 = step1[, sum(prodY), by="cat"]
我想知道是否可以避免这个加入步骤。这有几个原因 - 例如,如果x 很大,复制将使用额外的内存(我说的对吗?)。此外,这些重复行的汇总表非常混乱,使分析更容易出错。
因此,我考虑在每个dict$cat 中使用样本在x 中进行二分搜索。我知道如何为单个类别执行此操作,因此为所有类别执行此操作的一种丑陋方式是使用循环:
setkey(x, samp)
setkey(dict,samp)
pool = vector("list")
for(n in unique(dict$cat)){
thisCat = x[J(dict[cat==n])]
setkey(thisCat, samp)
step1 = thisCat[, list(prodY=prod(y)[1], cat=cat[1]), by="samp"]
pool[[n]] = step1[, sum(prodY), by="cat"]
}
resMet2 = rbindlist(pool)
但当然要避免这样的循环。所以我想知道是否有任何方法可以让data.table 迭代J() 内部的键值?
【问题讨论】:
标签: r data.table