¿Cómo aleatorizar (o permutar) un dataframe a la vez y en forma de columna?

Tengo un dataframe (df1) como este.

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 columna d1 … d4 es el nombre de la fila, la fila f1 … f5 es el nombre de la columna.

Para hacer una muestra (df1), obtengo un nuevo dataframe con un recuento de 1 igual que df1. Por lo tanto, el recuento de 1 se conserva para el dataframe completo, pero no para cada fila o cada columna.

¿Es posible hacer la aleatorización en fila o en columna?

Quiero aleatorizar la columna de df1 para cada columna, es decir, el número de 1 en cada columna sigue siendo el mismo. y cada columna necesita ser cambiada por al menos una vez. Por ejemplo, puedo tener un df2 aleatorizado como este: (Tomé nota de que el recuento de 1 en cada columna sigue siendo el mismo, pero el recuento de 1 en cada fila es diferente.

  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 

Del mismo modo, también quiero aleatorizar el df1 por filas para cada fila, es decir, el no. de 1 en cada fila sigue siendo el mismo, y cada fila necesita ser cambiada (pero el número de entradas modificadas podría ser diferente). Por ejemplo, un df3 aleatorizado podría ser algo como esto:

  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 

PD. Muchas gracias por la ayuda de Gavin Simpson, Joris Meys y Chase por las respuestas anteriores a mi pregunta anterior sobre la asignación aleatoria de dos columnas.

Dado el R data.frame:

 > df1 abc 1 1 1 0 2 1 0 0 3 0 1 0 4 0 0 0 

Baraja por filas:

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

Por defecto, sample() reordena aleatoriamente los elementos pasados ​​como primer argumento. Esto significa que el tamaño predeterminado es el tamaño de la matriz pasada. Al pasar el parámetro replace=FALSE (por defecto) a la sample(...) asegura que el muestreo se realiza sin reemplazo, lo que logra un cambio aleatorio en filas.

Mezcle en forma de columna:

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

Eche un vistazo a permatswap() en el paquete vegano . Aquí hay un ejemplo que mantiene los totales de fila y columna, pero puede relajar eso y corregir solo una de las sums de fila o columna.

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

Esto da:

 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 

Para explicar la llamada:

 out <- permatswap(mat, times = 99, burnin = 20000, thin = 500, mtype = "prab") 
  1. times es el número de matrices aleatorias que desea, aquí 99
  2. burnin es el número de intercambios realizados antes de comenzar a tomar muestras aleatorias. Esto permite que la matriz de la que tomamos muestra sea bastante aleatoria antes de comenzar a tomar cada una de nuestras matrices aleatorizadas
  3. thin dice que solo toma un sorteo al azar cada thin intercambio
  4. mtype = "prab" dice que trata la matriz como presencia / ausencia, es decir datos binarios 0/1.

Un par de cosas a tener en cuenta, esto no garantiza que ninguna columna o fila se haya asignado al azar, pero si burnin es lo suficientemente largo, debería haber una buena posibilidad de que eso haya sucedido. Además, podría dibujar más matrices aleatorias de las que necesita y descartar aquellas que no coinciden con todos sus requisitos.

Su requisito de tener diferentes números de cambios por fila, tampoco está cubierto aquí. De nuevo, puede muestrear más matrices de las que desea y luego descartar las que no cumplen con este requisito también.

también puedes usar la función randomizeMatrix en el paquete R picante

ejemplo:

 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 > 

La opción null.model="frequency" mantiene las sums de las columnas y la richness mantiene las sums de las filas. Aunque se usa principalmente para aleatorizar conjuntos de datos de ausencia de presencia de especies en ecología comunitaria, funciona bien aquí.

Esta función también tiene otras opciones de modelo nulo; consulte el siguiente enlace para obtener más detalles (página 36) de la documentación de picante

Por supuesto, puedes muestrear cada fila:

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

barajará las filas, por lo que el número de 1 en cada fila no cambiará. Pequeños cambios y también funciona muy bien con columnas, pero este es un ejercicio para el lector 😛

Esta es otra forma de barajar el data.frame usando el paquete dplyr :

fila-sabio:

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

o

 df2 <- sample_frac(df1, 1L) 

en cuanto a la columna:

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

Muestras aleatorias y permutaciones en un dataframe Si está en forma de matriz convertir a datos.frame use la función de muestra del paquete base indexes = sample (1: nrow (df1), size = 1 * nrow (df1)) Muestras aleatorias y permutaciones