web-dev-qa-db-ja.com

データフレームのグループごとにn個のランダムな行をサンプリングする

これらの質問から- Rデータフレームのサブセットからの行のランダムサンプルデータフレーム内のランダムな行のサンプル 「n」行からランダムにサンプル(選択)する方法が簡単にわかりますdf、またはdf内の特定のレベルの要因から発生する「n」行。

サンプルデータを次に示します。

_df <- data.frame(matrix(rnorm(80), nrow=40))
df$color <-  rep(c("blue", "red", "yellow", "pink"), each=10)

df[sample(nrow(df), 3), ] #samples 3 random rows from df, without replacement.
_

例えば「ピンク」色からランダムな3行をサンプリングします-library(kimisc)を使用して:

_library(kimisc)
sample.rows(subset(df, color == "pink"), 3)
_

またはカスタム関数を書く:

_sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
sample.df(subset(df, color == "pink"), 3)
_

ただし、要因の各レベルから3(またはn)のランダムな行をサンプリングします。つまり新しいdfは12行(青から3行、赤から3行、黄色から3行、ピンクから3行)になります。これを数回実行し、各色のnewdfを作成し、それらを結合することは明らかに可能ですが、より簡単なソリューションを探しています。

24
jalapic

aveを使用して、特定の因子レベルを持つ各要素にランダムIDを割り当てることができます。次に、特定の範囲内のすべてのランダムIDを選択できます。

rndid <- with(df, ave(X1, color, FUN=function(x) {sample.int(length(x))}))
df[rndid<=3,]

これには、元の行の順序と行名を保存するという利点があります。さらに、rndidベクトルを再利用して、さまざまな長さのサブセットを簡単に作成できます。

6
MrFlick

dplyr 0.3以降のバージョンでは、これは問題なく機能します。

df %>% group_by(color) %>% sample_n(size = 3)

dplyrの古いバージョン(バージョン<= 0.2)

dplyrを使用してこれに答えようとしましたが、これが機能すると仮定します。

df %.% group_by(color) %.% sample_n(size = 3)

しかし、0.2ではsample_n.grouped_df S3メソッドは存在しますが、NAMESPACEファイルに登録されていないため、ディスパッチされません。代わりに、私はこれをしなければなりませんでした:

df %.% group_by(color) %.% dplyr:::sample_n.grouped_df(size = 3)
Source: local data frame [12 x 3]
Groups: color

            X1         X2  color
8   0.66152710 -0.7767473   blue
1  -0.70293752 -0.2372700   blue
2  -0.46691793 -0.4382669   blue
32 -0.47547565 -1.0179842   pink
31 -0.15254540 -0.6149726   pink
39  0.08135292 -0.2141423   pink
15  0.47721644 -1.5033192    red
16  1.26160230  1.1202527    red
12 -2.18431919  0.2370912    red
24  0.10493757  1.4065835 yellow
21 -0.03950873 -1.1582658 yellow
28 -2.15872261 -1.5499822 yellow

おそらくこれは将来のアップデートで修正されるでしょう。

28
joran

my stratified function を検討します。これは現在GitHub Gistとしてホストされています。

以下で入手:

_library(devtools)  ## To download "stratified"
source_Gist("https://Gist.github.com/mrdwab/6424112")
_

そしてそれを以下で使用します:

_stratified(df, "color", 3)
_

層別サンプリングに便利な機能がいくつかあります。たとえば、「オンザフライ」のサンプルソートを使用することもできます。

_stratified(df, "color", 3, select = list(color = c("blue", "red")))
_

関数の機能を理解するために、stratifiedの引数を次に示します。

  • df:入力_data.frame_
  • group:「層」を構成する1つまたは複数の列の文字ベクトル。
  • size:希望するサンプルサイズ。
    • sizeが1未満の値の場合、各階層から比例サンプルが取得されます。
    • sizeが1以上の単一の整数である場合、そのサンプル数は各階層から取得されます。
    • sizeが整数のベクトルの場合、指定された数のサンプルが各ストラタムに対して取得されます。 という名前のベクターを使用することをお勧めします。たとえば、2つの階層「A」と「B」があり、「A」の5つのサンプルと「B」の10つのサンプルが必要な場合は、size = c(A = 5, B = 10)と入力します。
  • select:これにより、サンプリングプロセスでグループをサブセット化できます。これはlistです。たとえば、group変数が「Group」で、3つの階層「A」、「B」、および「C」が含まれていたが、「A」と「C」からのみサンプリングしたい場合、select = list(Group = c("A", "C"))を使用できます。
  • replace:置換を伴うサンプリング用。

これが解決策です。 data.frameをカラーグループに分割します。次に、各グループから3行をサンプリングします。これにより、data.framesのリストが生成されます。

df2 <- lapply(split(df, df$color),
   function(subdf) subdf[sample(1:nrow(subdf), 3),]
)

目的の結果を得るために、data.framesのリストを1つのdata.frameにマージします。

do.call('rbind', df2)
##                    X1          X2  color
## blue.3    -1.22677188  1.25648082   blue
## blue.4    -0.54516686 -1.94342967   blue
## blue.1     0.44647071  0.16283326   blue
## pink.40    0.23520296 -0.40411906   pink
## pink.34    0.02033939 -0.32321309   pink
## pink.33   -1.01790533 -1.22618575   pink
## red.16     1.86545895  1.11691250    red
## red.11     1.35748078 -0.36044728    red
## red.13    -0.02425645  0.85335279    red
## yellow.21  1.96728782 -1.81388110 yellow
## yellow.25 -0.48084967  0.07865186 yellow
## yellow.24 -0.07056236 -0.28514125 yellow
6
gagolews

基本的に、複数のグループと置換を使用したサンプリングを可能にする方法を以下に示します。

n <- 3
resample <- TRUE
index <- 1:nrow(df)
fun <- function(x) sample(x, n, replace = resample)
a <- aggregate(index, by = list(group = df$color), FUN = fun )

df[c(a$x),]

別のグループを追加するには、集約する 'by'引数にグループを含めます。

0
user3357177