J'ai une liste de dictionnaires comme ceci:
[{'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'}]
Et je veux transformer cela en un pandas DataFrame
comme ceci:
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
Remarque: l'ordre des colonnes n'a pas d'importance.
Comment transformer la liste des dictionnaires en un pandas DataFrame, comme indiqué ci-dessus?
Supposons que d
soit votre liste de dict, simplement:
pd.DataFrame(d)
Dans pandas16.2, je devais faire pd.DataFrame.from_records(d)
pour que cela fonctionne.
Comment convertir une liste de dictionnaires en un pandas DataFrame?
Les autres réponses sont correctes, mais peu d'explications ont été données sur les avantages et les inconvénients de ces méthodes. Le but de cet article sera de montrer des exemples de ces méthodes dans différentes situations, de déterminer quand utiliser (et quand ne pas utiliser) et de suggérer des alternatives.
DataFrame()
, DataFrame.from_records()
et .from_dict()
Selon la structure et le format de vos données, il existe des situations dans lesquelles les trois méthodes fonctionnent ou certaines fonctionnent mieux que d'autres, ou certaines ne fonctionnent pas du tout.
Prenons un exemple très artificiel.
_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}]
_
Cette liste comprend des "enregistrements" avec toutes les clés présentes. C'est le cas le plus simple que vous puissiez rencontrer.
_# 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
_
orient='index'
_/_'columns'
_ Avant de continuer, il est important de faire la distinction entre les différents types d’orientations dictionnaires et le soutien aux pandas. Il existe deux types principaux: "colonnes" et "index".
_orient='columns'
_
Dans les dictionnaires ayant l’orientation "colonnes", leurs clés correspondent aux colonnes du DataFrame équivalent.
Par exemple, data
ci-dessus est dans l'orientation "colonnes".
_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
_
Remarque: Si vous utilisez _pd.DataFrame.from_records
_, l'orientation est supposée être "des colonnes" (vous ne pouvez pas spécifier autrement) et les dictionnaires seront chargés en conséquence.
_orient='index'
_
Avec cet orient, les touches sont supposées correspondre aux valeurs d'index. Ce type de données convient mieux pour _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
_
Ce cas n'est pas pris en compte dans le PO, mais il reste utile de le savoir.
Si vous avez besoin d'un index personnalisé sur la DataFrame résultante, vous pouvez le définir à l'aide de l'argument _index=...
_.
_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
_
Ceci n'est pas supporté par _pd.DataFrame.from_dict
_.
Toutes les méthodes fonctionnent prêtes à l'emploi lors de la gestion de dictionnaires avec des clés/valeurs de colonne manquantes. Par exemple,
_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
_
"Et si je ne veux pas lire dans chaque colonne"? Vous pouvez facilement spécifier cela à l'aide du paramètre _columns=...
_.
Par exemple, à partir du dictionnaire d'exemple de _data2
_ ci-dessus, si vous souhaitez lire uniquement les colonnes "A", "D" et "F", vous pouvez le faire en passant une liste:
_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
_
Ceci n'est pas supporté par _pd.DataFrame.from_dict
_ avec les "colonnes" par défaut orient.
_pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
_
_ValueError: cannot use columns parameter with orient='columns'
_
Non pris en charge par l'une de ces méthodes directement . Vous devrez parcourir vos données et effectuer un suppression inverse sur place au fur et à mesure de votre itération. Par exemple, pour extraire uniquement le 0th et 2dakota du Nord lignes de _data2
_ ci-dessus, vous pouvez utiliser:
_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
_
json_normalize
pour les données imbriquéesUne alternative forte et robuste aux méthodes décrites ci-dessus est la fonction _json_normalize
_ qui fonctionne avec des listes de dictionnaires (enregistrements) et qui permet également de gérer des dictionnaires imbriqués.
_pd.io.json.json_normalize(data)
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
_
_pd.io.json.json_normalize(data2)
A B C D E
0 5.0 NaN 3 3.0 NaN
1 NaN 4.0 7 NaN 6.0
_
Encore une fois, n'oubliez pas que les données transmises à _json_normalize
_ doivent être au format liste de dictionnaires (enregistrements).
Comme indiqué, _json_normalize
_ peut également gérer des dictionnaires imbriqués. Voici un exemple tiré de la documentation.
_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
_
Pour plus d'informations sur les arguments meta
et _record_path
_, consultez la documentation.
Voici un tableau de toutes les méthodes décrites ci-dessus, ainsi que des fonctionnalités/fonctionnalités prises en charge.
* Utilisez _orient='columns'
_ puis transposez pour obtenir le même effet que _orient='index'
_.
Vous pouvez également utiliser pd.DataFrame.from_dict(d)
comme:
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
Je sais que quelques personnes tomberont sur cela et ne trouveront rien qui puisse l’aider. La façon la plus simple que j'ai trouvée de le faire est la suivante:
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)
J'espère que ça aide quelqu'un!