web-dev-qa-db-ja.com

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
_

私は次のようなことを考えていました:DT[ , sample(??, 3), by = a]は、「a」ごとに3行のサンプルを返します(返される行の順序は重要ではありません)。

_    a   b
 1: 2 180
 2: 2  57
 3: 2 799
 4: 1  69
 5: 1 347
 6: 1 732
_
30

多分このようなもの?

> 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

(以下の修正をしてくれたJoshに感謝します。)

40
joran

ジョランの答えはさらに一般化できると思います。詳細はここにあります( 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
8

David Arenburgによるこの回答 に触発されて、_.SD_の割り当てを回避する別の方法は、グループをサンプリングし、_.EACHI_を使用して元のデータに結合することです。

_DT[ DT[, sample(.N, 3), by=a], b[i.V1], on="a", by=.EACHI]

#    a  V1
# 1: 2  42
# 2: 2 498
# 3: 2 179
# 4: 1 469
# 5: 1  93
# 6: 1 898
_

ここで、DT[, sample(.N, 3), by=a]行は各グループのサンプルを示しています

_#         a V1
# 1:      1  9
# 2:      1  3
# 3:      1  2
# 4:      2  4
# 5:      2  9
# ---          
_

したがって、_V1_を使用して、対応するbを取得できます。

2
SymbolixAU

層化サンプリング >オーバーサンプリング

size=don[y==1,.(strata=length(iden)),by=.(y,x)] # count of iden by strata   
table(don$x,don$y) 

don<-merge(don,size[,.(y,strata)],by="x") #merge strata values  
don_strata=don[,.SD[sample(.N,strata)],by=.(y,x)]
0
Marimono