我有兩個data.tables:一個實驗數據表x
和一個類別查找表dict
。如何在data.table中執行「串行連接」?
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()
中的關鍵值?
很酷,非常感謝! – msp
我不知道%的百分比是以這種方式優化的。 – msp
請參閱[此自動索引的要點](https://gist.github.com/arunsrinivasan/dacb9d1cac301de8d9ff)。在某個時候,我會把它包裝成一個小插曲。 – Arun