Wie kann ein Datenrahmen zeilenweise und spaltenweise randomisiert (oder permutiert) werden?

96

Ich habe einen Datenrahmen (df1) wie diesen.

     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

Die Spalte d1 ... d4 ist der Rowname, die Zeile f1 ... f5 ist der Spaltenname.

Um Beispiel (df1) zu machen, erhalte ich einen neuen Datenrahmen mit der Anzahl 1, der mit df1 identisch ist. Die Anzahl 1 bleibt also für den gesamten Datenrahmen erhalten, jedoch nicht für jede Zeile oder Spalte.

Ist es möglich, die Randomisierung zeilenweise oder spaltenweise durchzuführen?

Ich möchte die df1 spaltenweise für jede Spalte randomisieren, dh die Zahl 1 in jeder Spalte bleibt gleich. und jede Spalte muss mindestens einmal geändert werden. Zum Beispiel kann ich eine zufällige df2 wie diese haben: (Es wurde festgestellt, dass die Anzahl von 1 in jeder Spalte gleich bleibt, aber die Anzahl von 1 in jeder Zeile unterschiedlich ist.

     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

Ebenso möchte ich auch die df1 zeilenweise für jede Zeile randomisieren, dh die Nr. von 1 in jeder Zeile bleibt gleich und jede Zeile muss geändert werden (aber die Anzahl der geänderten Einträge kann unterschiedlich sein). Zum Beispiel könnte ein randomisierter df3 ungefähr so ​​aussehen:

     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. Vielen Dank für die Hilfe von Gavin Simpson, Joris Meys und Chase für die vorherigen Antworten auf meine vorherige Frage zur Randomisierung von zwei Spalten.

a83
quelle
Möchten Sie sowohl die Zeile als auch die Spalten gleichzeitig permutieren? Beim erneuten Lesen sieht es so aus, als ob die Spaltenbeschränkung (gleiche Anzahl von Einsen in jeder Spalte) in Ihrem zweiten Beispiel für das Permutieren von Zeilen nicht gültig war.
Gavin Simpson
1
Bitte melden Sie sich nicht für mehrere Konten an. Ich habe die Moderatoren gebeten, das hier verwendete Konto mit dem Konto des vorherigen Q zusammenzuführen.
Gavin Simpson

Antworten:

233

Angesichts des R-Datenrahmens:

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

Reihenweise mischen:

> 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

Standardmäßig sample()werden die als erstes Argument übergebenen Elemente nach dem Zufallsprinzip neu angeordnet. Dies bedeutet, dass die Standardgröße die Größe des übergebenen Arrays ist. Durch Übergeben des Parameters replace=FALSE(Standardeinstellung) wird sample(...)sichergestellt, dass die Abtastung ersatzlos erfolgt, wodurch ein zeilenweises Mischen durchgeführt wird.

Spaltenweise mischen:

> 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
pms
quelle
5
Ich finde es lustig, dass dies nicht der Top-Kommentar ist, und dennoch ist es einfacher, als etwas anderes zu lernen. Das gilt für fast jede Frage zum Permutieren. BENUTZEN SIE NUR BEISPIEL ()!
Dreistes Gleichgewicht
Bin ich zu Recht davon ausgegangen, dass diese Methode die row.names beibehält?
tumultous_rooster
Gibt es einen Grund für die Verwendung von = über dem Standard <- in diesem Fall?
Christian
4
Nun, dies ändert die Reihenfolge der Zeilen und Spalten, aber was OP wollte, ist anders: Mischen Sie jede Spalte / Zeile unabhängig
JelenaČuklina
genau das was ich brauchte!
ChuckCottrill
18

Dies ist eine weitere Möglichkeit, das data.frameusing-Paket zu mischen dplyr:

Reihenweise:

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

oder

df2 <- sample_frac(df1, 1L)

Spaltenweise:

df2 <- select(df1, one_of(sample(names(df1)))) 
Enrique Pérez Herrero
quelle
10

Schauen Sie sich permatswap()das vegane Paket an. Hier ist ein Beispiel, in dem sowohl Zeilen- als auch Spaltensummen beibehalten werden. Sie können dies jedoch lockern und nur eine der Zeilen- oder Spaltensummen korrigieren.

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")

Das gibt:

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

Um den Anruf zu erklären:

out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab")
  1. times ist die Anzahl der gewünschten zufälligen Matrizen, hier 99
  2. burninist die Anzahl der getauschten Swaps, bevor wir mit der Stichprobenentnahme beginnen. Dies ermöglicht, dass die Matrix, aus der wir eine Stichprobe erstellen, ziemlich zufällig ist, bevor wir mit der Entnahme jeder unserer randomisierten Matrizen beginnen
  3. thinsagt, nimm nur einen zufälligen Draw bei jedem thinSwap
  4. mtype = "prab" sagt, behandeln Sie die Matrix als Anwesenheit / Abwesenheit, dh binäre 0/1-Daten.

Ein paar Dinge zu beachten, dies garantiert nicht, dass eine Spalte oder Zeile zufällig ausgewählt wurde, aber wenn sie burninlang genug ist, sollte eine gute Chance bestehen, dass dies passiert ist. Außerdem können Sie mehr zufällige Matrizen zeichnen, als Sie benötigen, und solche verwerfen, die nicht allen Ihren Anforderungen entsprechen.

Ihre Anforderung, eine unterschiedliche Anzahl von Änderungen pro Zeile vorzunehmen, wird hier ebenfalls nicht behandelt. Auch hier können Sie mehr Matrizen abtasten, als Sie möchten, und dann diejenigen verwerfen, die diese Anforderung ebenfalls nicht erfüllen.

Gavin Simpson
quelle
6

Sie können die randomizeMatrixFunktion auch im R-Paket verwendenpicante

Beispiel:

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
> 

Die Option null.model="frequency"verwaltet Spaltensummen und richnessZeilensummen. Obwohl es hauptsächlich zur Randomisierung von Datensätzen zur Abwesenheit von Arten in der Gemeinschaftsökologie verwendet wird, funktioniert es hier gut.

Diese Funktion bietet auch andere Nullmodelloptionen. Weitere Informationen (Seite 36) der Dokumentation finden Sie unter folgendem Link (Seite 36) picante

Anne Heloise Theo
quelle
4

Natürlich können Sie jede Zeile probieren:

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

mischt die Zeilen selbst, sodass sich die Anzahl der Zeilen 1in jeder Zeile nicht ändert. Kleine Änderungen und es funktioniert auch gut mit Spalten, aber dies ist eine Übung für den Leser :-P

binfalse
quelle
2
Es gibt nichts in dem, was versucht, die Einschränkungen zu implementieren, die das OP auferlegen möchte.
Gavin Simpson
2

Sie können auch die gleiche Anzahl von Elementen in Ihrem Datenrahmen mit so etwas "abtasten":

nr<-dim(M)[1]
random_M = M[sample.int(nr),]
Marcos
quelle
Stattdessen dim(M)[1]können Sie verwenden, nrow(M)damit das gesamte Verfahren zu einem Einzeiler wird:random_M <- M[nrow(M),]
Agile Bean
1

Wenn das Ziel darin besteht, jede Spalte zufällig zu mischen, funktionieren einige der obigen Antworten nicht, da die Spalten gemeinsam gemischt werden (dies bewahrt die Korrelationen zwischen den Spalten). Andere erfordern die Installation eines Pakets. Es gibt jedoch einen Einzeiler:

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

Zufällige Stichproben und Permutationen in einem Datenrahmen Wenn diese in Matrixform in data.frame konvertiert sind, verwenden Sie die Beispielfunktion aus den Basispaketindizes = sample (1: nrow (df1), size = 1 * nrow (df1)) Zufällige Stichproben und Permutationen

Thrinadhn
quelle