117 votes

Comment randomiser (ou permuter) un dataframe dans le sens des lignes et des colonnes ?

J'ai un dataframe (df1) comme ceci.

     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

La colonne d1...d4 est le nom de l'utilisateur, la ligne f1...f5 est le nom de la colonne.

En faisant sample(df1), j'obtiens un nouveau dataframe avec un nombre de 1 identique à df1. Le nombre de 1 est donc conservé pour l'ensemble du dataframe mais pas pour chaque ligne ou chaque colonne.

Est-il possible d'effectuer la randomisation en ligne ou en colonne ?

Je veux randomiser le df1 pour chaque colonne, c'est-à-dire que le nombre de 1 dans chaque colonne reste le même. et chaque colonne doit être modifiée au moins une fois. Par exemple, je peux avoir un df2 aléatoire comme ceci : (Notez que le nombre de 1 dans chaque colonne reste le même mais que le nombre de 1 dans chaque ligne est différent.

     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

De même, je souhaite également randomiser le df1 par ligne pour chaque ligne, c'est-à-dire que le nombre de 1 dans chaque ligne reste le même et que chaque ligne doit être modifiée (mais le nombre d'entrées modifiées peut être différent). Par exemple, un df3 aléatoire pourrait être quelque chose comme ceci :

     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. Merci beaucoup à Gavin Simpson, Joris Meys et Chase pour leurs réponses à ma question précédente sur la randomisation de deux colonnes.

262voto

pms Points 900

Étant donné le cadre de données R :

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

Mélanger les rangs dans le sens de la longueur :

> 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

Par défaut sample() réorganise de manière aléatoire les éléments transmis en tant que premier argument. Cela signifie que la taille par défaut est la taille du tableau passé. Passage du paramètre replace=FALSE (par défaut) à sample(...) garantit que l'échantillonnage est effectué sans remplacement, ce qui permet de mélanger les rangées.

Mélanger les colonnes :

> 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

28voto

C'est une autre façon de mélanger les data.frame utiliser le paquet dplyr :

dans le sens des rangs :

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

o

df2 <- sample_frac(df1, 1L)

en colonnes :

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

12voto

Gavin Simpson Points 72349

Jetez un coup d'œil à permatswap() dans le végétalien l'emballage. Voici un exemple de gestion des totaux des lignes et des colonnes, mais il est possible d'assouplir cette règle et de ne fixer qu'une seule des sommes des lignes ou des colonnes.

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

Cela donne :

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

Expliquer l'appel :

out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab")
  1. times est le nombre de matrices aléatoires que vous souhaitez, ici 99
  2. burnin est le nombre d'échanges effectués avant le début du prélèvement d'échantillons aléatoires. Cela permet à la matrice à partir de laquelle nous prélevons des échantillons d'être tout à fait aléatoire avant de commencer à prélever chacune de nos matrices aléatoires.
  3. thin ne procède à un tirage au sort que tous les thin échanges
  4. mtype = "prab" dit traiter la matrice comme une présence/absence, c'est-à-dire comme des données binaires 0/1.

Il convient de noter que cela ne garantit pas qu'une colonne ou une ligne a été randomisée, mais si burnin est suffisamment longue, il y a de bonnes chances que cela se soit produit. Vous pouvez également tirer plus de matrices aléatoires que vous n'en avez besoin et écarter celles qui ne répondent pas à toutes vos exigences.

Votre besoin d'avoir différents nombres de modifications par ligne n'est pas non plus couvert ici. Là encore, vous pouvez échantillonner plus de matrices que vous ne le souhaitez et écarter celles qui ne répondent pas à cette exigence.

9voto

Vous pouvez également utiliser la fonction randomizeMatrix dans le paquetage R picante

exemple :

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
> 

L'option null.model="frequency" maintient les sommes des colonnes et les richness maintient les sommes des lignes. Bien qu'il soit principalement utilisé pour randomiser des ensembles de données sur la présence et l'absence d'espèces en écologie des communautés, il fonctionne bien ici.

Cette fonction offre également d'autres options de modèle nul, consultez le lien suivant pour plus de détails (page 36) sur le modèle nul. picante la documentation

4voto

binfalse Points 398

Bien entendu, vous pouvez échantillonner chaque ligne :

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

mélangera lui-même les rangées, de sorte que le nombre de 1 dans chaque ligne ne change pas. De petits changements et cela fonctionne aussi très bien avec les colonnes, mais c'est un exercice pour le lecteur :-P

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X