Tengo una lista anidada de datos. Su longitud es 132 y cada elemento es una lista de longitud 20. ¿Hay un rápido manera de convertir esta estructura en un marco de datos que tenga 132 filas y 20 columnas de datos?
Aquí hay algunos datos de muestra para trabajar:
l <- replicate(
132,
list(sample(letters, 20)),
simplify = FALSE
)
Respuestas:
Asumiendo que su lista de listas se llama
l
:Lo anterior convertirá todas las columnas de caracteres en factores, para evitar esto, puede agregar un parámetro a la llamada data.frame ():
fuente
Con
rbind
Editar: Versión anterior de retorno
data.frame
delist
's en lugar de vectores (como @IanSudbery señaló en los comentarios).fuente
rbind(your_list)
devuelve una matriz de lista 1x32?do.call
pasa elementos deyour_list
como argumentos arbind
. Es equivalenterbind(your_list[[1]], your_list[[2]], your_list[[3]], ....., your_list[[length of your_list]])
.your_list
contenga vectores de igual tamaño.NULL
tiene longitud 0, por lo que debería fallar.Puedes usar el
plyr
paquete. Por ejemplo, una lista anidada del formularioahora tiene una longitud de 4 y cada lista
l
contiene otra lista de la longitud 3. Ahora puede ejecutary debería obtener el mismo resultado que en la respuesta @Marek y @nico.
fuente
matrix
enfoque.data.frame(t(sapply(mylistlist,c)))
sapply
lo convierte en una matriz.data.frame
Convierte la matriz en un marco de datos.fuente
c
de jugar aquí, una instancia de los datos de la lista? Oh, espera, c para la función concatenada ¿verdad? Confundirse con el uso de @ mnel de c. También estoy de acuerdo con @dchandler, obtener los nombres de columna correctos fue una necesidad valiosa en mi caso de uso. Solución brillante?c
:Combine Values into a Vector or List
asume que tu lista se llama
L
,fuente
data.frame(Reduce(rbind, list(c('col1','col2'))))
produce un marco de datos con 2 filas, 1 columna (esperaba 1 fila 2 columnas)El paquete
data.table
tiene la funciónrbindlist
que es una implementación súper rápida dedo.call(rbind, list(...))
.Puede tomar una lista de
lists
,data.frames
odata.tables
como entrada.Esto devuelve una
data.table
herencia dedata.frame
.Si realmente desea volver a convertir a un data.frame use
as.data.frame(DT)
fuente
setDF
ahora permite volver a data.frame por referencia.El
tibble
paquete tiene una funciónenframe()
que resuelve este problema mediante la coerción delist
objetos anidados a objetos anidadostibble
(marco de datos "ordenado"). Aquí hay un breve ejemplo de R para Data Science :Como tiene varios nidos en su lista,
l
puede usar elunlist(recursive = FALSE)
para eliminar el anidamiento innecesario para obtener una sola lista jerárquica y luego pasar aenframe()
. Utilizotidyr::unnest()
para descomponer la salida en un marco de datos "ordenado" de un solo nivel, que tiene sus dos columnas (una para el gruponame
y otra para las observaciones con los gruposvalue
). Si desea columnas que se amplíen, puede agregar una columnaadd_column()
que simplemente repita el orden de los valores 132 veces. Entonces solospread()
los valores.fuente
Dependiendo de la estructura de sus listas, hay algunas
tidyverse
opciones que funcionan bien con listas de longitud desigual:También puede mezclar vectores y marcos de datos:
fuente
X2
no se puede convertir de entero a carácterReshape2 produce el mismo resultado que el ejemplo de plyr anterior:
rendimientos:
Si estaba casi sin píxeles, podría hacer esto todo en 1 línea con recast ().
fuente
Este método utiliza un
tidyverse
paquete ( ronroneo ).La lista:
Convirtiéndolo en un marco de datos (
tibble
más específicamente):fuente
Ampliando la respuesta de @ Marek: si desea evitar que las cadenas se conviertan en factores y la eficiencia no es una preocupación, intente
fuente
Para el caso general de listas profundamente anidadas con 3 o más niveles como los obtenidos de un JSON anidado:
considere el enfoque de
melt()
convertir la lista anidada a un formato alto primero:seguido por
dcast()
entonces para ampliarse nuevamente en un conjunto de datos ordenado donde cada variable forma una columna y cada observación forma una fila:fuente
Más respuestas, junto con tiempos en la respuesta a esta pregunta: ¿Cuál es la forma más eficiente de emitir una lista como un marco de datos?
La forma más rápida, que no produce un marco de datos con listas en lugar de vectores para columnas parece ser (de la respuesta de Martin Morgan):
fuente
Algunas veces sus datos pueden ser una lista de listas de vectores de la misma longitud.
(Los vectores internos también podrían ser listas, pero estoy simplificando para que sea más fácil de leer).
Entonces puedes hacer la siguiente modificación. Recuerde que puede anular la lista de un nivel a la vez:
Ahora use su método favorito mencionado en las otras respuestas:
fuente
Esto es lo que finalmente funcionó para mí:
do.call("rbind", lapply(S1, as.data.frame))
fuente
fuente
Para una solución en paralelo (multinúcleo, multisesión, etc.) que utiliza una
purrr
familia de soluciones, use:Donde
l
esta la listaPara comparar el más eficiente
plan()
que puede usar:fuente
El siguiente comando simple funcionó para mí:
Referencia ( respuesta de Quora )
Pero esto fallará si no es obvio cómo convertir la lista a un marco de datos:
Nota : La respuesta es hacia el título de la pregunta y puede omitir algunos detalles de la pregunta.
fuente
Una forma corta (pero quizás no la más rápida) de hacerlo sería utilizar la base r, ya que un marco de datos es solo una lista de vectores de igual longitud . Por lo tanto, la conversión entre su lista de entrada y un marco de datos de 30 x 132 sería:
Desde allí, podemos transponerlo a una matriz de 132 x 30 y convertirlo nuevamente en un marco de datos:
Como una línea:
Los nombres de las filas serán bastante molestos de ver, pero siempre puede cambiar el nombre de aquellos con
rownames(new_df) <- 1:nrow(new_df)
fuente
¿Qué hay de usar
map_
función junto con unfor
bucle? Aquí está mi solución:donde
map_dfr
convertir cada elemento de la lista en un data.frame y luegorbind
unirlos por completo.En su caso, supongo que sería:
fuente