R data.table:来自第二个表的组的随机行样本

时间:2019-08-23 00:45:56

标签: r data.table

假设我们有两个表,每个表之间都有一个共同的组指示符。然后,对于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万行。

2 个答案:

答案 0 :(得分:3)

您的需求的直接翻译是:

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

答案 1 :(得分:2)

这是使用dplyr的一种方法,我相信这也可以转换为data.table。逻辑是我们首先计算DT1中每个组的行数,left_joinDT2group并使用sample随机选择{{1 }}行中的每个n * 2

group