web-dev-qa-db-ja.com

Rデータフレームのサブセットからの行のランダムサンプル

データフレームの一部から行のサンプルを取得する良い方法はありますか?

次のようなデータがある場合

gender <- c("F", "M", "M", "F", "F", "M", "F", "F")
age    <- c(23, 25, 27, 29, 31, 33, 35, 37)

そうすれば、3つのFの年齢を簡単にサンプリングできます。

sample(age[gender == "F"], 3)

のようなものを取得します

[1] 31 35 29

しかし、このデータをデータフレームに変換すると

mydf <- data.frame(gender, age) 

当たり前のことは使えない

sample(mydf[mydf$gender == "F", ], 3)

私は次のような不条理な数の括弧で複雑なものを作ることができますが

mydf[sample((1:nrow(mydf))[mydf$gender == "F"], 3), ]

そして私が欲しいものを手に入れます

  gender age
7      F  35
4      F  29
1      F  23

書く方法を考えるのに時間がかからないより良い方法はありますか?

12
Henry

あなたの複雑な方法は、ほとんどそれを行う方法です-私はすべての答えがそのテーマのバリエーションになると思います。

たとえば、最初にmydf$gender=="F"インデックスを生成するのが好きです。

idx <- which(mydf$gender=="F")

それから私はそれからサンプリングします:

mydf[ sample(idx,3), ]

したがって、1行で(ただし、角かっこの数を減らし、複数行にすることでコードを理解しやすくすることができます)。

mydf[ sample( which(mydf$gender=='F'), 3 ), ]

「私はハッカーです!」私の一部はワンライナーを好みます、私の賢明な部分は、2ライナーは2行ですが、それははるかに理解しやすいと言います-それはあなたの選択です。

19

あなたは言う私は明白なものを使うことができない:

_sample(mydf[mydf$gender == "F", ], 3)
_

しかし、それを行うための独自の関数を書くことができます:

_sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
_

次に、サブセット選択で実行します。

_sample.df(mydf[mydf$gender == "F", ], 3)
#   gender age
# 5      F  31
# 4      F  29
# 1      F  23
_

(個人的にはsample.df(subset(mydf, gender == "F"), 3)が読みやすいと思います。)

9
flodel

これは、私のパッケージのsampleの拡張バージョンでより簡単になりました。

library(devtools); install_github('kimisc', 'krlmlr')

library(kimisc)
sample.rows(subset(mydf, gender == "F"), 3)

詳細については、こちら 関連する回答 も参照してください。

2
krlmlr