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
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.
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
.
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
“¿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'
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
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.
Aquí hay una tabla de todos los métodos mencionados anteriormente, junto con las características / funcionalidades compatibles.
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