簡體   English   中英

R data.table:來自第二個表的組的隨機行樣本

[英]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_joinDT2 ,然后使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM