データフレームを行ごとおよび列ごとにランダム化(または置換)する方法


96

私はこのようなデータフレーム(df1)を持っています。

     f1   f2   f3   f4   f5
d1   1    0    1    1    1  
d2   1    0    0    1    0
d3   0    0    0    1    1
d4   0    1    0    0    1

d1 ... d4列は行名、f1 ... f5行は列名です。

sample(df1)を実行するには、df1と同じカウント1の新しいデータフレームを取得します。したがって、1のカウントはデータフレーム全体で保存されますが、各行または各列では保存されません。

行ごとまたは列ごとにランダム化を行うことはできますか?

各列のdf1を列ごとにランダム化します。つまり、各列の1の数は同じままです。また、各列は少なくとも1回は変更する必要があります。たとえば、次のようなランダム化されたdf2があるとします(各列の1のカウントは同じままですが、各行の1のカウントは異なることに注意してください。

     f1   f2   f3   f4   f5
d1   1    0    0    0    1  
d2   0    1    0    1    1
d3   1    0    0    1    1
d4   0    0    1    1    0

同様に、各行の行ごとにdf1をランダム化したい、つまり、いいえ。各行の1は同じままで、各行を変更する必要があります(ただし、変更されたエントリの数は異なる場合があります)。たとえば、ランダム化されたdf3は次のようになります。

     f1   f2   f3   f4   f5
d1   0    1    1    1    1  <- two entries are different
d2   0    0    1    0    1  <- four entries are different
d3   1    0    0    0    1  <- two entries are different
d4   0    0    1    0    1  <- two entries are different

PS。2つの列のランダム化に関する私の以前の質問に対する以前の回答に対するGavin Simpson、Joris Meys、およびChaseの助けに感謝します。


列の両方を同時に並べ替えますか?これをもう一度読むと、列の制約(各列に同じ数の1がある)は、行を並べ替える2番目の例では保持されていなかったようです。
Gavin Simpson

1
複数のアカウントにサインアップしないでください。私はあなたが以前Q.上で使用したもので、ここで使用するアカウントマージするモデレータを求めている
ギャビン・シンプソン

回答:


233

R data.frameを考える:

> df1
  a b c
1 1 1 0
2 1 0 0
3 0 1 0
4 0 0 0

行ごとにシャッフル:

> df2 <- df1[sample(nrow(df1)),]
> df2
  a b c
3 0 1 0
4 0 0 0
2 1 0 0
1 1 1 0

デフォルトでsample()は、最初の引数として渡された要素をランダムに並べ替えます。つまり、デフォルトのサイズは、渡された配列のサイズです。パラメーターを渡すreplace=FALSE(デフォルト)sample(...)ことで、行ごとのシャッフルを実現する置換なしでサンプリングが行われるようにします。

列ごとにシャッフル:

> df3 <- df1[,sample(ncol(df1))]
> df3
  c a b
1 0 1 1
2 0 1 0
3 0 0 1
4 0 0 0

5
これがトップのコメントではないのはおかしいと思いますが、他のパッケージについて学習するよりも簡単です。これは、並べ替えに関するほとんどすべての質問に当てはまります。SAMPLE()を使用するだけです!
Brash Equilibrium

このメソッドがrow.namesを維持すると仮定して、私は正しいですか?
tumultous_rooster 2013年

この場合、標準よりも=を使用する理由<-
クリスチャン

4
まあ、これは行と列の順序を変更しているが、何OPが望んでいたことは異なります。独立し、各列/行をシャッフル
JelenaČuklina

まさに私が必要とするもの!
ChuckCottrill 2018

18

これは、data.frameusingパッケージをシャッフルする別の方法dplyrです。

行ごと:

df2 <- slice(df1, sample(1:n()))

または

df2 <- sample_frac(df1, 1L)

列ごと:

df2 <- select(df1, one_of(sample(names(df1)))) 

10

見てみましょうpermatswap()ビーガンパッケージを。以下は、行と列の両方の合計を維持する例ですが、これを緩和して、行または列の合計の1つだけを修正できます。

mat <- matrix(c(1,1,0,0,0,0,0,1,1,0,0,0,1,1,1,0,1,0,1,1), ncol = 5)
set.seed(4)
out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab")

これは与える:

R> out$perm[[1]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    1    1    1
[2,]    0    1    0    1    0
[3,]    0    0    0    1    1
[4,]    1    0    0    0    1
R> out$perm[[2]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    0    1    1
[2,]    0    0    0    1    1
[3,]    1    0    0    1    0
[4,]    0    0    1    0    1

通話について説明するには:

out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab")
  1. times 必要なランダム化された行列の数です。ここでは99
  2. burninランダムサンプルの取得を開始する前に行われたスワップの数です。これにより、ランダム化された各マトリックスの取得を開始する前に、サンプリング元のマトリックスを非常にランダムにすることができます
  3. thinthinスワップごとにランダムなドローのみを取ると言う
  4. mtype = "prab" マトリックスを存在/不在、つまりバイナリ0/1データとして扱うと言います。

注意すべき点が2つあります。これは、列または行がランダム化されていることを保証するものでburninはありませんが、十分に長い場合は、その可能性が高いはずです。また、必要以上にランダムな行列を描画し、すべての要件に一致しないものを破棄することもできます。

行ごとに異なる数の変更を行うという要件についても、ここでは取り上げません。この場合も、必要以上の行列をサンプリングして、この要件を満たさない行列を破棄することもできます。


6

randomizeMatrixRパッケージの関数を使用することもできますpicante

例:

test <- matrix(c(1,1,0,1,0,1,0,0,1,0,0,1,0,1,0,0),nrow=4,ncol=4)
> test
     [,1] [,2] [,3] [,4]
[1,]    1    0    1    0
[2,]    1    1    0    1
[3,]    0    0    0    0
[4,]    1    0    1    0

randomizeMatrix(test,null.model = "frequency",iterations = 1000)

     [,1] [,2] [,3] [,4]
[1,]    0    1    0    1
[2,]    1    0    0    0
[3,]    1    0    1    0
[4,]    1    0    1    0

randomizeMatrix(test,null.model = "richness",iterations = 1000)

     [,1] [,2] [,3] [,4]
[1,]    1    0    0    1
[2,]    1    1    0    1
[3,]    0    0    0    0
[4,]    1    0    1    0
> 

このオプションnull.model="frequency"は、列の合計をrichness維持し、行の合計を維持します。主にコミュニティ生態学で種の存在不在のデータセットをランダム化するために使用されますが、ここではうまく機能します。

この関数には他のnullモデルオプションもあります。ドキュメントの詳細(36ページ)については、次のリンクを確認してください picante


4

もちろん、各行をサンプリングできます。

sapply (1:4, function (row) df1[row,]<<-sample(df1[row,]))

行自体をシャッフルするため、各行のの数は1変わりません。小さな変更であり、列でもうまく機能しますが、これは読者のための練習です:-P


2
OPが課したい制約を実装しようとするものは何もありません。
Gavin Simpson

2

次のようなものを使用して、データフレーム内の同じ数のアイテムを「サンプリング」することもできます。

nr<-dim(M)[1]
random_M = M[sample.int(nr),]

代わりにdim(M)[1]、あなたが使用することができnrow(M)、全体の手順は、ワンライナーになるので:random_M <- M[nrow(M),]
アジャイル豆

1

目標が各列をランダムにシャッフルすることである場合、列が一緒にシャッフルされるため、上記の回答の一部は機能しません(これにより、列間の相関関係が維持されます)。他の人はパッケージをインストールする必要があります。しかし、ワンライナーが存在します:

df2 = lapply(df1, function(x) { sample(x) })

0

データフレーム内のランダムサンプルと順列マトリックス形式の場合、data.frameに変換します。基本パッケージインデックスのサンプル関数を使用しますindex = sample(1:nrow(df1)、size = 1 * nrow(df1))ランダムサンプルと順列

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.