Convierta la lista de diccionarios en un DataFrame de pandas

9 minutos de lectura

Convierta la lista de diccionarios en un DataFrame de pandas
AppleLover

Tengo una lista de diccionarios como este:

[{'points': 50, 'time': '5:00', 'year': 2010}, 
{'points': 25, 'time': '6:00', 'month': "february"}, 
{'points':90, 'time': '9:00', 'month': 'january'}, 
{'points_h1':20, 'month': 'june'}]

Y quiero convertir esto en un panda DataFrame Me gusta esto:

      month  points  points_h1  time  year
0       NaN      50        NaN  5:00  2010
1  february      25        NaN  6:00   NaN
2   january      90        NaN  9:00   NaN
3      june     NaN         20   NaN   NaN

Nota: El orden de las columnas no importa.

¿Cómo puedo convertir la lista de diccionarios en un DataFrame de pandas como se muestra arriba?

1646969588 520 Convierta la lista de diccionarios en un DataFrame de pandas
joris

Suponiendo que d es su lista de dictados, simplemente:

df = pd.DataFrame(d)

Nota: esto no funciona con datos anidados.

  • ¿Cómo podría uno usar uno de los pares clave/valor como índice (por ejemplo, tiempo)?

    – CatsLoveJazz

    28 de junio de 2016 a las 13:37

  • @CatsLoveJazz Puedes simplemente hacer df = df.set_index('time') después

    – joris

    28 de junio de 2016 a las 13:38

  • @CatsLoveJazz No, eso no es posible cuando se convierte desde un dict.

    – joris

    29 de junio de 2016 a las 8:16

  • A partir de Pandas 0.19.2, no se menciona esto en la documentación, al menos no en los documentos para pandas.DataFrame

    – Leo Alekseyev

    13 abr 2017 a las 22:56

  • Tenga en cuenta que para un diccionario anidado '{"":{"... usa el enfoque json_normalize, vea la respuesta detallada de @ cs95

    – questionto42standswithUkraine

    27 mayo 2020 a las 22:16

1646969588 303 Convierta la lista de diccionarios en un DataFrame de pandas
cs95

¿Cómo convierto una lista de diccionarios en un DataFrame de pandas?

Las otras respuestas son correctas, pero no se ha explicado mucho en términos de ventajas y limitaciones de estos métodos. El objetivo de esta publicación será mostrar ejemplos de estos métodos en diferentes situaciones, discutir cuándo usarlos (y cuándo no usarlos) y sugerir alternativas.


DataFrame(), DataFrame.from_records()y .from_dict()

Según la estructura y el formato de sus datos, hay situaciones en las que funcionan los tres métodos, o algunos funcionan mejor que otros, o algunos no funcionan en absoluto.

Considere un ejemplo muy artificial.

np.random.seed(0)
data = pd.DataFrame(
    np.random.choice(10, (3, 4)), columns=list('ABCD')).to_dict('r')

print(data)
[{'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]

Esta lista consta de “registros” con todas las claves presentes. Este es el caso más simple que podría encontrar.

# The following methods all produce the same output.
pd.DataFrame(data)
pd.DataFrame.from_dict(data)
pd.DataFrame.from_records(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

Palabra en Orientaciones del Diccionario: orient="index"/'columns'

Antes de continuar, es importante hacer la distinción entre los diferentes tipos de orientaciones del diccionario y el soporte con pandas. Hay dos tipos principales: “columnas” e “índice”.

orient="columns"

Los diccionarios con la orientación de “columnas” tendrán sus claves correspondientes a las columnas en el DataFrame equivalente.

Por ejemplo, data arriba está en el oriente de “columnas”.

data_c = [
 {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]
pd.DataFrame.from_dict(data_c, orient="columns")

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

Nota: Si está utilizando pd.DataFrame.from_recordsse supone que la orientación es “columnas” (no puede especificar lo contrario), y los diccionarios se cargarán en consecuencia.

orient="index"

Con esta orientación, se supone que las claves corresponden a valores de índice. Este tipo de datos es más adecuado para pd.DataFrame.from_dict.

data_i ={
 0: {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 1: {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 2: {'A': 2, 'B': 4, 'C': 7, 'D': 6}}
pd.DataFrame.from_dict(data_i, orient="index")

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

Este caso no se considera en el OP, pero aún así es útil saberlo.

Configuración del índice personalizado

Si necesita un índice personalizado en el DataFrame resultante, puede configurarlo usando el index=... argumento.

pd.DataFrame(data, index=['a', 'b', 'c'])
# pd.DataFrame.from_records(data, index=['a', 'b', 'c'])

   A  B  C  D
a  5  0  3  3
b  7  9  3  5
c  2  4  7  6

Esto no está respaldado por pd.DataFrame.from_dict.

Manejo de claves/columnas faltantes

Todos los métodos funcionan de manera inmediata cuando se manejan diccionarios a los que les faltan claves o valores de columna. Por ejemplo,

data2 = [
     {'A': 5, 'C': 3, 'D': 3},
     {'A': 7, 'B': 9, 'F': 5},
     {'B': 4, 'C': 7, 'E': 6}]
# The methods below all produce the same output.
pd.DataFrame(data2)
pd.DataFrame.from_dict(data2)
pd.DataFrame.from_records(data2)

     A    B    C    D    E    F
0  5.0  NaN  3.0  3.0  NaN  NaN
1  7.0  9.0  NaN  NaN  NaN  5.0
2  NaN  4.0  7.0  NaN  6.0  NaN

Subconjunto de lectura de columnas

“¿Qué pasa si no quiero leer en cada columna”? Puede especificar esto fácilmente usando el columns=... parámetro.

Por ejemplo, del diccionario de ejemplos de data2 arriba, si desea leer solo las columnas “A”, “D” y “F”, puede hacerlo pasando una lista:

pd.DataFrame(data2, columns=['A', 'D', 'F'])
# pd.DataFrame.from_records(data2, columns=['A', 'D', 'F'])

     A    D    F
0  5.0  3.0  NaN
1  7.0  NaN  5.0
2  NaN  NaN  NaN

Esto no está respaldado por pd.DataFrame.from_dict con las “columnas” de orientación predeterminadas.

pd.DataFrame.from_dict(data2, orient="columns", columns=['A', 'B'])
ValueError: cannot use columns parameter with orient="columns"

Leer subconjunto de filas

No compatible con ninguno de estos métodos directamente. Tendrá que iterar sobre sus datos y realizar una eliminación inversa en el lugar mientras itera. Por ejemplo, para extraer solo el 0el y 2Dakota del Norte filas de data2 arriba, puedes usar:

rows_to_select = {0, 2}
for i in reversed(range(len(data2))):
    if i not in rows_to_select:
        del data2[i]

pd.DataFrame(data2)
# pd.DataFrame.from_dict(data2)
# pd.DataFrame.from_records(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

La panacea: json_normalize para datos anidados

Una alternativa fuerte y robusta a los métodos descritos anteriormente es el json_normalize función que trabaja con listas de diccionarios (registros), y además también puede manejar diccionarios anidados.

pd.json_normalize(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6
pd.json_normalize(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

Una vez más, tenga en cuenta que los datos pasados ​​a json_normalize debe estar en formato de lista de diccionarios (registros).

Como se mencionó, json_normalize también puede manejar diccionarios anidados. Aquí hay un ejemplo tomado de la documentación.

data_nested = [
  {'counties': [{'name': 'Dade', 'population': 12345},
                {'name': 'Broward', 'population': 40000},
                {'name': 'Palm Beach', 'population': 60000}],
   'info': {'governor': 'Rick Scott'},
   'shortname': 'FL',
   'state': 'Florida'},
  {'counties': [{'name': 'Summit', 'population': 1234},
                {'name': 'Cuyahoga', 'population': 1337}],
   'info': {'governor': 'John Kasich'},
   'shortname': 'OH',
   'state': 'Ohio'}
]
pd.json_normalize(data_nested, 
                          record_path="counties", 
                          meta=['state', 'shortname', ['info', 'governor']])

         name  population    state shortname info.governor
0        Dade       12345  Florida        FL    Rick Scott
1     Broward       40000  Florida        FL    Rick Scott
2  Palm Beach       60000  Florida        FL    Rick Scott
3      Summit        1234     Ohio        OH   John Kasich
4    Cuyahoga        1337     Ohio        OH   John Kasich

Para obtener más información sobre el meta y record_path argumentos, echa un vistazo a la documentación.


resumiendo

Aquí hay una tabla de todos los métodos discutidos anteriormente, junto con las características/funcionalidad compatibles.

ingrese la descripción de la imagen aquí

* Utilizar orient="columns" y luego transponer para obtener el mismo efecto que orient="index".

  • ¡Guau! De acuerdo, esto junto con Merging SO post pertenecen a la API. Debería contribuir a la documentación de pandas si aún no lo ha hecho. Ted Petrou acaba de publicar un Artículo de LinkedIn sobre la popularidad de pandas en Stack Overflow y menciona que la falta de buena documentación contribuye al volumen de preguntas aquí.

    –Scott Boston

    18 dic 2018 a las 13:50

  • @ScottBoston Tienes toda la razón, lo he escuchado suficientes veces ahora que sé que es algo en lo que debería pensar más seriamente. Creo que la documentación puede ser una excelente manera de ayudar a los usuarios, más que publicar preguntas que solo llegarían a una fracción de la misma audiencia.

    – cs95

    18 de diciembre de 2018 a las 13:59

  • Es particularmente problemático porque los detalles de qué métodos son buenos para qué casos a menudo cambian, por lo que tener respuestas muy largas y profundas en SO no solo no es tan útil como tenerlo en la documentación oficial de pandas, pero a menudo es incluso dañino o engañoso. porque algún cambio en las funciones internas puede hacer que la respuesta sea incorrecta o de hecho incorrecta y no está claramente vinculada al repositorio de origen real para marcar la actualización de la documentación.

    – ely

    18 de diciembre de 2018 a las 14:06

  • es una buena respuesta, creo que es hora de que volvamos a entrar en esas preguntas comunes en la versión más actual de pandas 🙂

    – BENY

    18 de diciembre de 2018 a las 14:48

  • @ely: esa nunca es una razón para no escribir respuestas aquí, de todos modos. Ninguna La respuesta puede volverse obsoleta, eso es lo que hemos votado, y aquí existen diferentes perspectivas y diferentes objetivos, y siempre es valioso tener diferentes formas de explicar lo mismo.

    – Martijn Pieters

    22 de enero de 2019 a las 16:11

1646969589 407 Convierta la lista de diccionarios en un DataFrame de pandas
szeitlin

En pandas 16.2, tuve que hacer pd.DataFrame.from_records(d) para que esto funcione.

  • lo bueno de este enfoque es que también funciona con deque

    – MBZ

    12 de octubre de 2015 a las 5:22

  • funciona bien con pandas 0.17.1 con la solución de @joris

    – Antón Protopopov

    19 de enero de 2016 a las 10:14

  • Usar 0.14.1 y la solución de @joris no funcionó, pero esto sí

    – mchen

    15/04/2016 a las 10:55

  • En 0.18.1hay que usar from_records si los diccionarios no tienen todos las mismas claves.

    – fredcallaway

    24/10/2016 a las 21:49

Convierta la lista de diccionarios en un DataFrame de pandas
shivsn

También puedes usar pd.DataFrame.from_dict(d) como :

In [8]: d = [{'points': 50, 'time': '5:00', 'year': 2010}, 
   ...: {'points': 25, 'time': '6:00', 'month': "february"}, 
   ...: {'points':90, 'time': '9:00', 'month': 'january'}, 
   ...: {'points_h1':20, 'month': 'june'}]

In [12]: pd.DataFrame.from_dict(d)
Out[12]: 
      month  points  points_h1  time    year
0       NaN    50.0        NaN  5:00  2010.0
1  february    25.0        NaN  6:00     NaN
2   january    90.0        NaN  9:00     NaN
3      june     NaN       20.0   NaN     NaN

1646969591 652 Convierta la lista de diccionarios en un DataFrame de pandas
soum

Pyhton3:
La mayoría de las soluciones enumeradas anteriormente funcionan. Sin embargo, hay casos en los que no se requiere el número de fila del marco de datos y cada fila (registro) debe escribirse individualmente.

El siguiente método es útil en ese caso.

import csv

my file="C:\Users\John\Desktop\export_dataframe.csv"

records_to_save = data2 #used as in the thread. 


colnames = list[records_to_save[0].keys()] 
# remember colnames is a list of all keys. All values are written corresponding
# to the keys and "None" is specified in case of missing value 

with open(myfile, 'w', newline="",encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(colnames)
    for d in records_to_save:
        writer.writerow([d.get(r, "None") for r in colnames])

1646969588 303 Convierta la lista de diccionarios en un DataFrame de pandas
cs95

La forma más fácil que he encontrado para hacerlo es así:

dict_count = len(dict_list)
df = pd.DataFrame(dict_list[0], index=[0])
for i in range(1,dict_count-1):
    df = df.append(dict_list[i], ignore_index=True)

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad