Tengo un data.frame que me gustaría convertir en una lista por filas, lo que significa que cada fila correspondería a sus propios elementos de lista. En otras palabras, me gustaría una lista que sea tan larga como data.frame tenga filas.
Hasta ahora, he abordado este problema de la siguiente manera, pero me preguntaba si hay una mejor manera de abordarlo.
xy.df <- data.frame(x = runif(10), y = runif(10))
# pre-allocate a list and fill it with a loop
xy.list <- vector("list", nrow(xy.df))
for (i in 1:nrow(xy.df)) {
xy.list[[i]] <- xy.df[i,]
}
split
cada elemento tiene tipo endata.frame with 1 rows and N columns
lugar delist of length N
split
, probablemente debería hacer lodrop=T
contrario, sus niveles originales de factores no caeránEureka!
fuente
unlist(apply(xy.df, 1, list), recursive = FALSE)
. Sin embargo, la solución de flodel es más eficiente que usarapply
ot
.t
conviertedata.fame
a amatrix
para que los elementos en su lista sean vectores atómicos, no una lista como la OP solicitada. Por lo general, no es un problema hasta quexy.df
contiene tipos mixtos ...apply
. En realidad, es solo un bucle for implementado en R.lapply
realiza el bucle en C, que es significativamente más rápido. Este formato de lista de filas es realmente preferible si está haciendo muchos bucles.apply
versión es.mapply(data.frame, xy.df, NULL)
Si desea abusar por completo de data.frame (como lo hago yo) y desea mantener la funcionalidad $, una forma es dividir data.frame en data.frames de una línea reunidos en una lista:
No es solo una masturbación intelectual, sino que permite 'transformar' el data.frame en una lista de sus líneas, manteniendo la indexación $ que puede ser útil para su uso posterior con lapply (suponiendo que la función que pasa a lapply usa esta indexación $)
fuente
data.frame
s en una soladata.frame
?Una solución más moderna usa solo
purrr::transpose
:fuente
Trabajé en esto hoy para un data.frame (realmente un data.table) con millones de observaciones y 35 columnas. Mi objetivo era devolver una lista de data.frames (data.tables) cada uno con una sola fila. Es decir, quería dividir cada fila en un marco de datos independiente y almacenarlos en una lista.
Aquí hay dos métodos que se me ocurrieron que fueron aproximadamente 3 veces más rápidos que
split(dat, seq_len(nrow(dat)))
para ese conjunto de datos. A continuación, comparo los tres métodos en un conjunto de datos de 7500 filas y 5 columnas ( iris repetido 50 veces).Esto vuelve
Si bien las diferencias no son tan grandes como en mi prueba anterior, el
setDF
método directo es significativamente más rápido en todos los niveles de distribución de ejecuciones con max (setDF) <min (split) y elattr
método suele ser más del doble de rápido.Un cuarto método es el campeón extremo, que es un simple anidado
lapply
, que devuelve una lista anidada. Este método ejemplifica el costo de construir un data.frame a partir de una lista. Además, todos los métodos que probé con ladata.frame
función fueron aproximadamente un orden de magnitud más lentos que lasdata.table
técnicas.datos
fuente
Parece que una versión actual del
purrr
paquete (0.2.2) es la solución más rápida:Comparemos las soluciones más interesantes:
Resultados:
También podemos obtener el mismo resultado con
Rcpp
:Ahora caompare con
purrr
:Resultados:
fuente
by_row()
ahora se mudó alibrary(purrrlyr)
Un par de opciones más:
Con
asplit
Con
split
yrow
datos
fuente
La mejor manera para mí fue:
Datos de ejemplo:
Llamamos a la
BBmisc
bibliotecaY el resultado será:
fuente
Una forma alternativa es convertir el df en una matriz y luego aplicar la
lappy
función de aplicación de lista sobre él:ldf <- lapply(as.matrix(myDF), function(x)x)
fuente
Otra alternativa de uso
library(purrr)
(que parece ser un poco más rápido en grandes data.frames)fuente
Como escribió @flodel: Esto convierte su marco de datos en una lista que tiene el mismo número de elementos que el número de filas en el marco de datos:
Además, puede agregar una función para seleccionar solo aquellas columnas que no son NA en cada elemento de la lista:
fuente
La
by_row
función delpurrrlyr
paquete lo hará por usted.Este ejemplo demuestra
Por defecto, el valor devuelto desde
myfn
se coloca en una nueva columna de lista en el df llamado.out
. El$.out
final de la declaración anterior selecciona inmediatamente esta columna, devolviendo una lista de listas.fuente