Ответ 1
Предположим, что d
- ваш список dicts, просто:
pd.DataFrame(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'}]
И я хочу превратить это в DataFrame
панд, как это:
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
Примечание: порядок столбцов не имеет значения.
Как я могу превратить список словарей в pandas DataFrame, как показано выше?
Предположим, что d
- ваш список dicts, просто:
pd.DataFrame(d)
В пандах 16.2 мне пришлось сделать pd.DataFrame.from_records(d)
чтобы заставить это работать.
Как преобразовать список словарей в панду DataFrame?
Другие ответы верны, но мало что было объяснено с точки зрения преимуществ и ограничений этих методов. Целью этого поста будет показать примеры этих методов в различных ситуациях, обсудить, когда использовать (а когда не использовать), и предложить альтернативы.
DataFrame()
, DataFrame.from_records()
и .from_dict()
В зависимости от структуры и формата ваших данных, существуют ситуации, когда либо все три метода работают, либо одни работают лучше других, либо некоторые не работают вообще.
Рассмотрим очень надуманный пример.
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 th и 2 nd из 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
для вложенных данныхСильной и надежной альтернативой описанным выше методам является функция 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'
.
Вы также можете использовать pd.DataFrame.from_dict(d)
как:
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
Я знаю, что несколько человек столкнутся с этим и не найдут здесь ничего полезного. Я нашел самый простой способ сделать это так:
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)
Надеюсь, это кому-нибудь поможет!