Jak przekonwertować listę słowników na pandę DataFrame?
Pozostałe odpowiedzi są poprawne, ale niewiele wyjaśniono w kategoriach zalet i ograniczeń tych metod. Celem tego postu będzie pokazanie przykładów tych metod w różnych sytuacjach, omówienie, kiedy stosować (a kiedy nie) i zaproponowanie alternatyw.
W zależności od struktury i formatu danych istnieją sytuacje, w których albo wszystkie trzy metody działają, albo niektóre działają lepiej niż inne, albo niektóre wcale nie działają.
Rozważ bardzo wymyślony przykład.
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}]
Ta lista składa się z „zapisów” z każdym kluczem. To najprostszy przypadek, jaki można napotkać.
# 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
Słowo na temat orientacji słownika: orient='index'
/'columns'
Zanim przejdziesz dalej, ważne jest, aby wprowadzić rozróżnienie między różnymi typami orientacji słownikowych i wspierać pandy. Istnieją dwa podstawowe typy: „kolumny” i „indeks”.
orient='columns'
Słowniki o orientacji „kolumny” będą miały klucze odpowiadające kolumnom w równoważnej ramce danych.
Na przykład data
powyżej znajduje się w orientacji „kolumny”.
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
Uwaga: Jeśli używasz pd.DataFrame.from_records
, zakłada się, że orientacja to „kolumny” (nie można określić inaczej), a słowniki zostaną odpowiednio załadowane.
orient='index'
Przy takim ukierunkowaniu zakłada się, że klucze odpowiadają wartościom indeksu. Tego rodzaju dane najlepiej nadają się 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
Ten przypadek nie jest rozpatrywany w PO, ale nadal warto o nim wiedzieć.
Ustawianie indeksu niestandardowego
Jeśli potrzebujesz wynikowego indeksu w wynikowej ramce danych, możesz ustawić go za pomocą index=...
argumentu.
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
To nie jest obsługiwane przez pd.DataFrame.from_dict
.
Radzenie sobie z brakującymi kluczami / kolumnami
Wszystkie metody działają od razu po wyjęciu z pudełka podczas obsługi słowników z brakującymi wartościami kluczy / kolumn. Na przykład,
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
Czytanie podzbioru kolumn
„Co jeśli nie chcę czytać w każdej kolumnie”? Możesz to łatwo określić za pomocą columns=...
parametru.
Na przykład z powyższego słownika data2
, jeśli chcesz czytać tylko kolumny „A”, „D” i „F”, możesz to zrobić, przekazując listę:
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
Nie jest to obsługiwane przez pd.DataFrame.from_dict
domyślny orient „kolumny”.
pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError: cannot use columns parameter with orient='columns'
Czytanie podzbioru wierszy
Nie jest obsługiwany przez każdy z tych metod bezpośrednio . Będziesz musiał wykonać iterację swoich danych i wykonać odwrotne usuwanie w miejscu podczas iteracji. Na przykład, aby wyodrębnić tylko 0 th i 2 nd wiersze z data2
powyżej, można użyć:
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
Panacea: json_normalize
dla danych zagnieżdżonych
Silną, niezawodną alternatywą dla metod opisanych powyżej jest json_normalize
funkcja, która działa z listami słowników (rekordów), a ponadto może obsługiwać zagnieżdżone słowniki.
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
Ponownie pamiętaj, że przekazywane dane json_normalize
muszą mieć format listy słowników (rekordów).
Jak wspomniano, json_normalize
może również obsługiwać zagnieżdżone słowniki. Oto przykład zaczerpnięty z dokumentacji.
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
Więcej informacji na temat argumentów meta
i znajduje record_path
się w dokumentacji.
Zreasumowanie
Oto tabela wszystkich metod omówionych powyżej, wraz z obsługiwanymi funkcjami / funkcjonalnością.
* Użyj, orient='columns'
a następnie transponuj, aby uzyskać taki sam efekt jak orient='index'
.