Convertir la lista de diccionarios en un dataframe de pandas

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 DataFrame pandas como este:

  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?

Suponiendo que d es tu lista de dictados, simplemente:

 pd.DataFrame(d) 

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

(Respuesta 2019, vigente a partir de v0.24 ) Las otras respuestas son correctas, pero no se ha explicado mucho en términos de ventajas y limitaciones de estos métodos. El objective de este post será mostrar ejemplos de estos métodos en diferentes situaciones, discutir cuándo usar (y cuándo no usar) y sugerir alternativas.


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

Dependiendo de la estructura y el formato de sus datos, hay situaciones en las que los tres métodos funcionan, 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 consiste en “registros” con cada clave presente. Este es el caso más simple que podrías encontrar.

 # The following methods all produce the same output. pd.DataFrame(data) pd.DataFrame.from_dict(data) pd.DataFrame.from_records(data) ABCD 0 5 0 3 3 1 7 9 3 5 2 2 4 7 6 

Word en las orientaciones del diccionario

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

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

Por ejemplo, los data anteriores están en la orientación 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') ABCD 0 5 0 3 3 1 7 9 3 5 2 2 4 7 6 

Nota: Si está utilizando pd.DataFrame.from_records , se asume 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 asume que las claves corresponden a valores de índice. Este tipo de datos es el 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') ABCD 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 es útil saberlo.

Configuración de índice personalizado

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

 pd.DataFrame(data, index=['a', 'b', 'c']) # pd.DataFrame.from_records(data, index=['a', 'b', 'c']) ABCD a 5 0 3 3 b 7 9 3 5 c 2 4 7 6 

Esto no es compatible con pd.DataFrame.from_dict .

Tratar con las claves / columnas que faltan

Todos los métodos funcionan de inmediato cuando se manejan diccionarios con claves / valores de columna faltantes. 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) ABCDEF 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 especificarlo fácilmente usando el parámetro columns=...

Por ejemplo, del ejemplo de diccionario de data2 anterior, 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']) ADF 0 5.0 3.0 NaN 1 7.0 NaN 5.0 2 NaN NaN NaN 

Esto no es compatible con pd.DataFrame.from_dict con las “columnas” pd.DataFrame.from_dict predeterminadas.

 pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B']) 

 ValueError: cannot use columns parameter with orient='columns' 

Lectura de subconjunto de filas

No es compatible con ninguno de estos métodos directamente . Tendrá que iterar sobre sus datos y realizar una eliminación inversa en el lugar a medida que itere. Por ejemplo, para extraer solo las filas 0 y 2 de los data2 anteriores, puede 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) ABCDE 0 5.0 NaN 3 3.0 NaN 1 NaN 4.0 7 NaN 6.0 

La panacea: json_normalize

Una alternativa sólida y sólida a los métodos descritos anteriormente es la función json_normalize que funciona con listas de diccionarios (registros) y, además, también puede manejar diccionarios nesteds.

 pd.io.json.json_normalize(data) ABCD 0 5 0 3 3 1 7 9 3 5 2 2 4 7 6 

 pd.io.json.json_normalize(data2) ABCDE 0 5.0 NaN 3 3.0 NaN 1 NaN 4.0 7 NaN 6.0 

De nuevo, tenga en cuenta que los datos pasados ​​a json_normalize deben estar en el formato de lista de diccionarios (registros).

Como se mencionó, json_normalize también puede manejar diccionarios nesteds. 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.io.json.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 los argumentos meta y record_path , consulte la documentación.


Resumiendo

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

introduzca la descripción de la imagen aquí

También puede 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