Як перетворити список словників у пандус DataFrame?
Інші відповіді є правильними, але мало що було пояснено з точки зору переваг та обмежень цих методів. Метою цієї публікації буде показати приклади цих методів у різних ситуаціях, обговорити, коли їх використовувати (а коли не використовувати) та запропонувати альтернативи.
Залежно від структури та формату ваших даних, бувають ситуації, коли або всі три методи працюють, або деякі працюють краще, ніж інші, або деякі взагалі не працюють.
Розглянемо дуже надуманий приклад.
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}]
Цей список складається з "записів" з усіма присутніми клавішами. Це найпростіший випадок, з яким ви могли зіткнутися.
# 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'
Перш ніж продовжувати, важливо зробити відмінність між різними типами орієнтацій на словники та підтримати пандами. Існує два основних типи: "стовпці" та "індекс".
orient='columns'
Словники з орієнтацією "стовпці" матимуть свої ключі, що відповідають стовпцям у еквівалентній DataFrame.
Наприклад, data
вище в орієнтації «стовпчики».
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
Примітка. Якщо ви користуєтесь pd.DataFrame.from_records
, орієнтація вважається "стовпчиками" (не можна вказати інше), і словники будуть завантажені відповідно.
orient='index'
При такому орієнтації вважається, що ключі відповідають значенням індексу. Цей вид даних найкраще підходить 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
Цей випадок не розглядається в ОП, але все ж корисно знати.
Встановлення спеціального індексу
Якщо вам потрібен спеціальний індекс на результуючій DataFrame, ви можете встановити його за допомогою 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
Це не підтримується pd.DataFrame.from_dict
.
Робота зі відсутніми ключами / стовпцями
Усі методи спрацьовують під час роботи зі словниками із відсутніми значеннями ключів / стовпців. Наприклад,
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
Читання підмножини стовпців
"Що робити, якщо я не хочу читати в кожній колонці"? Ви можете легко вказати це за допомогою columns=...
параметра.
Наприклад, із прикладу словника data2
вище, якщо ви хочете читати лише стовпці "A", "D" і "F", ви можете зробити це, передавши список:
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
Це не підтримується, pd.DataFrame.from_dict
якщо орієнтовані "стовпці" за замовчуванням.
pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError: cannot use columns parameter with orient='columns'
Читання підмножини рядків
Не підтримується жодним із цих методів безпосередньо . Вам доведеться перебирати дані та виконувати зворотне видалення на місці під час ітерації. Наприклад, для витягування лише 0- го та 2- го рядків data2
зверху, ви можете використовувати:
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
функція, яка працює зі списками словників (записів), а крім того може також обробляти вкладені словники.
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
Знову ж таки, майте на увазі, що передані дані json_normalize
повинні бути у форматі списків словників (записів).
Як було сказано, json_normalize
також можна обробляти вкладені словники. Ось приклад, взятий з документації.
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
Для отримання додаткової інформації про meta
та record_path
аргументи, ознайомтеся з документацією.
Узагальнення
Ось таблиця всіх описаних вище методів, а також підтримувані функції / функціональність.
* Використовуйте orient='columns'
та переміщуйте, щоб отримати той же ефект, що і orient='index'
.