[英]R data.table: Random sample of rows from second table by group
假設我們有兩個表,每個表之間都有一個共同的組指標。 然后,對於DT1中的每一行,我們想從DT2中的每組中隨機選擇2行。
解決此問題的一種可能方法是在DT2中隨機生成一個與DT1的行重合的整數列,並將兩個表連接在一起。 但是行的數量因組而異,目前尚不清楚如何根據組的長度來進行限制。
最低工作示例:
DT1 <- data.table(var1=seq(1:20),
group=c(1,1,1,1,1,2,2,2,2,3,3,3,4,4,4,4,4,4,4,4))
DT2 <- data.table(obs=seq(1:13),
group=c(1,1,1,2,2,2,3,3,3,4,4,4,5))
視圖:
DT1
var1 group
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
6: 6 2
7: 7 2
8: 8 2
9: 9 2
10: 10 3
11: 11 3
12: 12 3
13: 13 4
14: 14 4
15: 15 4
16: 16 4
17: 17 4
18: 18 4
19: 19 4
20: 20 4
DT2
obs group
1: 1 1
2: 2 1
3: 3 1
4: 4 2
5: 5 2
6: 6 2
7: 7 3
8: 8 3
9: 9 3
10: 10 4
11: 11 4
12: 12 4
13: 13 5
因此,對於DT1中的每一行,我想將其與DT2中隨機選擇的2行按組進行配對。 預期結果可能類似於:
DT3
var1 group obs
1: 1 1 1
2: 1 1 3
3: 2 1 2
4: 2 1 3
...
37: 19 4 10
38: 19 4 11
39: 20 4 10
40: 20 4 12
如果需要說的話,實際的應用程序在DT1中有4億行,在DT2中有1000萬行。
您需求的直接翻譯是:
DT2[DT1, on=.(group), allow.cartesian=TRUE, .(var1, obs=obs[sample(.N, 2L)]), by=.EACHI]
這可能會更快:
gn <- DT1[, .(nsamp=2*.N), keyby=.(group)]
DT2[gn, on=.(group), .(obs=obs[sample(.N, nsamp, replace=TRUE)]), by=.EACHI][,
var1 := rep(DT1$var1, each=2L)]
數據:
set.seed(0L)
library(data.table)
DT1 <- data.table(var1=101:120, group=c(1,1,1,1,1,2,2,2,2,3,3,3,4,4,4,4,4,4,4,4))
DT2 <- data.table(obs=201:213, group=c(1,1,1,2,2,2,3,3,3,4,4,4,5))
樣本輸出:
group var1 obs
1: 1 101 203
2: 1 101 201
3: 1 102 202
4: 1 102 203
5: 1 103 203
6: 1 103 201
7: 1 104 203
8: 1 104 202
9: 1 105 202
10: 1 105 203
11: 2 106 204
12: 2 106 206
13: 2 107 204
14: 2 107 205
15: 2 108 205
16: 2 108 206
17: 2 109 205
18: 2 109 206
19: 3 110 209
20: 3 110 207
21: 3 111 209
22: 3 111 208
23: 3 112 207
24: 3 112 208
25: 4 113 210
26: 4 113 212
27: 4 114 211
28: 4 114 210
29: 4 115 211
30: 4 115 212
31: 4 116 211
32: 4 116 210
33: 4 117 211
34: 4 117 210
35: 4 118 210
36: 4 118 211
37: 4 119 212
38: 4 119 211
39: 4 120 210
40: 4 120 211
group var1 obs
這是使用dplyr
一種方法,我相信這也可以轉換為data.table
。 邏輯是我們首先計算DT1
每個組的行數, left_join
它們按group
left_join
到DT2
,然后使用sample
隨機選擇每個group
n * 2
行。
library(dplyr)
DT1 %>%
group_by(group) %>%
mutate(n = n()) %>%
left_join(DT2, by = "group") %>%
group_by(group) %>%
slice(sample(seq_len(n()), first(n) * 2, replace = TRUE)) %>%
select(-n)
# var1 group obs
# <int> <dbl> <int>
# 1 4 1 1
# 2 3 1 3
# 3 4 1 2
# 4 4 1 1
# 5 2 1 3
# 6 3 1 2
# 7 1 1 1
# 8 4 1 2
# 9 4 1 2
#10 3 1 2
# … with 30 more rows
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.