在data.table中对每个组内的随机行进行采样

Chr*_*ing 29 r data.table

您将如何使用data.table有效地获取数据框中每个组内的行样本?

DT = data.table(a = sample(1:2), b = sample(1:1000,20))
DT
    a   b
 1: 2 562
 2: 1 183
 3: 2 180
 4: 1 874
 5: 2 533
 6: 1  21
 7: 2  57
 8: 1  20
 9: 2  39
10: 1 948
11: 2 799
12: 1 893
13: 2 993
14: 1  69
15: 2 906
16: 1 347
17: 2 969
18: 1 130
19: 2 118
20: 1 732
Run Code Online (Sandbox Code Playgroud)

我想的是:DT[ , sample(??, 3), by = a]这会为每个"a"返回三行样本(返回行的顺序并不重要):

    a   b
 1: 2 180
 2: 2  57
 3: 2 799
 4: 1  69
 5: 1 347
 6: 1 732
Run Code Online (Sandbox Code Playgroud)

jor*_*ran 43

也许是这样的?

> DT[,.SD[sample(.N, min(3,.N))],by = a]
   a   b
1: 1 744
2: 1 497
3: 1 167
4: 2 888
5: 2 950
6: 2 343
Run Code Online (Sandbox Code Playgroud)

(感谢Josh的纠正,下面.)

  • @ChristopherManning - 我只是猜测,但是(如果真的很重要),在某些情况下,这可能会更快:`DT [DT [,sample(.I,3),by = a] [[2]], ]`.(`sample(.I,3)`对相对于`DT`的行号进行采样.这个调用的优点是它不需要在处理调用时完全填充每个子集`.SD`. (14认同)
  • 谢谢您的帮助!我还发现我可以使用`if`语句根据`a`的值有条件地改变每组返回的样本数:`DT [,.SD [样本(.N,if(a ==) 1)2 else 3)],by = a]` (2认同)

roa*_*dom 8

我相信朱兰的答案可以进一步推广.详细信息在这里(如何使用警告对data.table中的组进行采样)但我相信此解决方案可以解释没有"3"行可供采样的情况.

当它尝试从小于"x"公共值的行中采样"x"次时,当前解决方案将出错.在下面的例子中,x = 3.它考虑到了这个警告.(由nrussell完成的解决方案)

set.seed(123)
##
DT <- data.table(
  a=c(1,1,1,1:15,1,1), 
  b=sample(1:1000,20))
##
R> DT[,.SD[sample(.N,min(.N,3))],by = a]
     a   b
 1:  1 288
 2:  1 881
 3:  1 409
 4:  2 937
 5:  3  46
 6:  4 525
 7:  5 887
 8:  6 548
 9:  7 453
10:  8 948
11:  9 449
12: 10 670
13: 11 566
14: 12 102
15: 13 993
16: 14 243
17: 15  42
Run Code Online (Sandbox Code Playgroud)