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
rbindEditar: Versión anterior de retorno
data.framedelist's en lugar de vectores (como @IanSudbery señaló en los comentarios).fuente
rbind(your_list)devuelve una matriz de lista 1x32?do.callpasa elementos deyour_listcomo argumentos arbind. Es equivalenterbind(your_list[[1]], your_list[[2]], your_list[[3]], ....., your_list[[length of your_list]]).your_listcontenga vectores de igual tamaño.NULLtiene longitud 0, por lo que debería fallar.Puedes usar el
plyrpaquete. Por ejemplo, una lista anidada del formularioahora tiene una longitud de 4 y cada lista
lcontiene otra lista de la longitud 3. Ahora puede ejecutary debería obtener el mismo resultado que en la respuesta @Marek y @nico.
fuente
matrixenfoque.data.frame(t(sapply(mylistlist,c)))sapplylo convierte en una matriz.data.frameConvierte la matriz en un marco de datos.fuente
cde 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 Listasume 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.tabletiene la funciónrbindlistque es una implementación súper rápida dedo.call(rbind, list(...)).Puede tomar una lista de
lists,data.framesodata.tablescomo entrada.Esto devuelve una
data.tableherencia dedata.frame.Si realmente desea volver a convertir a un data.frame use
as.data.frame(DT)fuente
setDFahora permite volver a data.frame por referencia.El
tibblepaquete tiene una funciónenframe()que resuelve este problema mediante la coerción delistobjetos 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,
lpuede 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 gruponamey 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
tidyverseopciones que funcionan bien con listas de longitud desigual:También puede mezclar vectores y marcos de datos:
fuente
X2no 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
tidyversepaquete ( ronroneo ).La lista:
Convirtiéndolo en un marco de datos (
tibblemá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
purrrfamilia de soluciones, use:Donde
lesta 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 unforbucle? Aquí está mi solución:donde
map_dfrconvertir cada elemento de la lista en un data.frame y luegorbindunirlos por completo.En su caso, supongo que sería:
fuente