Konwertuj listę słowników do ramki danych pandy
Mam listę takich słowników:
[{'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'}]
A ja chcę zamienić to w pandy DataFrame
w ten sposób:
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
Uwaga: kolejność kolumn nie ma znaczenia.
Jak mogę przekształcić listę słowników w ramkę danych pandy, jak pokazano powyżej?
7 answers
Przypuśćmy, że d
to Twoja lista dictów, po prostu:
df = pd.DataFrame(d)
Uwaga: to nie działa z zagnieżdżonymi danymi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-22 17:24:12
Jak przekonwertować listę słowników na ramkę danych pandy?
Inne odpowiedzi są poprawne, ale niewiele zostało wyjaśnione pod względem zalet i ograniczeń tych metod. Celem tego postu będzie pokazanie przykładów tych metod w różnych sytuacjach, omówienie, kiedy używać (a kiedy nie używać) i zaproponowanie alternatyw.
DataFrame()
, DataFrame.from_records()
, oraz .from_dict()
W zależności od struktura i format danych są sytuacje, w których albo wszystkie trzy metody działają, albo niektóre działają lepiej niż inne, albo niektóre nie działają w ogóle.
Rozważ bardzo wymyślny 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" rekordów " z każdym obecnym kluczem. To najprostszy przypadek, z jakim można się spotkać.
# 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 w słowniku: orient='index'
/'columns'
Przed kontynuacją, ważne jest, aby dokonać rozróżnienia między różnymi typami słownikowe orientacje i wsparcie z pand. Istnieją dwa podstawowe typy: "kolumny" i "indeks".
orient='columns'
Słowniki z orientacją "kolumny" będą miały swoje klucze odpowiadające kolumnom w równoważnej ramce danych.
Na przykład, data
powyżej znajduje się w" kolumnach " orient.
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ę orientację jako "kolumny" (nie można określić inaczej), a słowniki zostaną załadowane odpowiednio.
orient='index'
Przy tym Oriencie przyjmuje się, że klucze odpowiadają wartościom indeksu. Tego rodzaju dane najlepiej nadają się do 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
Ta sprawa nie jest brana pod uwagę w OP, ale nadal jest przydatna do poznania.
Ustawienie Własnego Indeksu
Jeśli potrzebujesz indeksu na wynikowej ramce danych, możesz go ustawić za pomocą argumentu 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
To nie jest obsługiwane przez pd.DataFrame.from_dict
.
Radzenie sobie z zaginionymi Klucze / Kolumny
Wszystkie metody działają po wyjęciu z pudełka podczas obsługi słowników z brakującymi kluczami/wartościami 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
Odczyt podzbioru kolumn
"co jeśli nie chcę czytać w każdej kolumnie"? Można to łatwo określić za pomocą parametru columns=...
.
Na przykład, z przykładowego słownika data2
powyżej, jeśli chcesz czytać tylko kolumny "A", " D " i "F", możesz to zrobić, przekazując 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
To nie jest obsługiwane przez {[26] } z domyślnym orient "kolumny".
pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError: cannot use columns parameter with orient='columns'
Odczyt podzbioru wierszy
Nie wspierane przez żadną z tych metodbezpośrednio . W trakcie iteracji należy wykonać odwrotne usunięcie. Na przykład, aby wyodrębnić tylko 0th i 2ND wiersze z data2
powyżej, możesz 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
Panaceum: json_normalize
dla danych zagnieżdżonych
Mocną, solidną alternatywą dla opisanych powyżej metod jest funkcja json_normalize
, która działa z listami słowników (rekordów), a ponadto może obsługiwać również słowniki zagnieżdżone.
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
Ponownie należy pamiętać, że dane przekazywane do json_normalize
muszą znajdować się w formacie 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 dokumentacja.
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
Aby uzyskać więcej informacji na temat argumentów meta
i record_path
, zajrzyj do dokumentacji.
Podsumowanie
Oto tabela wszystkich metod omówionych powyżej, wraz z obsługiwanymi funkcjami / funkcjami.
* użyj orient='columns'
, a następnie TRANSPONUJ, aby uzyskać taki sam efekt jak orient='index'
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-08 11:42:24
W pandach 16.2, musiałem zrobić pd.DataFrame.from_records(d)
, żeby to zadziałało.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-14 13:12:38
Możesz również użyć pd.DataFrame.from_dict(d)
jako:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-07 06:03:08
Pyhton3: {]} Większość wymienionych wcześniej rozwiązań działa. Są jednak przypadki, gdy numer wiersza ramki danych nie jest wymagany i każdy wiersz (rekord) musi być zapisywany indywidualnie.
W takim przypadku użyteczna jest następująca metoda.
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])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Do konwersji listy słowników na ramkę danych pandy można użyć "append":
Mamy Słownik o nazwie dic
i dic ma 30 pozycji listy(list1
, list2
,..., list30
)
- Krok 1: zdefiniuj zmienną dla zachowania wyniku (ex:
total_df
) - Krok 2: zainicjalizuj
total_df
za pomocąlist1
- Krok 3: użyj pętli for, aby dodać wszystkie listy do
total_df
total_df=list1
nums=Series(np.arange(start=2, stop=31))
for num in nums:
total_df=total_df.append(dic['list'+str(num)])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-19 07:52:25
Najłatwiejszy sposób, jaki znalazłem, to tak:
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-01 11:04:58