Преобразовать вложенный словарь в dataframe
Имеются след. исходные данные , которые нужно преобразовать в dataframe :
[{'id': 11029,
'name': 'Ростовская область',
'parent': {'id': 26,
'name': 'Южный федеральный округ',
'parent': {'id': 225, 'name': 'Россия', 'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'}]
[{'id': 11162,
'name': 'Свердловская область',
'parent': {'id': 52,
'name': 'Уральский федеральный округ',
'parent': {'id': 225, 'name': 'Россия', 'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'}]
[{'id': 11179,
'name': 'Белоярский',
'parent': {'id': 99994,
'name': 'Белоярский район',
'parent': {'id': 11193,
'name': 'Ханты-Мансийский автономный округ - Югра',
'parent': {'id': 52,
'name': 'Уральский федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'},
'type': 'CITY'},
{'id': 20579,
'name': 'Белоярский',
'parent': {'id': 99947,
'name': 'Белоярский городской округ',
'parent': {'id': 11162,
'name': 'Свердловская область',
'parent': {'id': 52,
'name': 'Уральский федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'},
'type': 'VILLAGE'},
{'id': 138476,
'name': 'Белоярский',
'parent': {'id': 173541,
'name': 'Белоярское сельское поселение',
'parent': {'id': 99833,
'name': 'Новобурасский район',
'parent': {'id': 11146,
'name': 'Саратовская область',
'parent': {'id': 40,
'name': 'Приволжский федеральный '
'округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'},
'type': 'OTHER'},
'type': 'VILLAGE'}]
[{'id': 20282,
'name': 'Выборгский район',
'parent': {'id': 2,
'name': 'Санкт-Петербург',
'parent': {'id': 10174,
'name': 'Санкт-Петербург и Ленинградская область',
'parent': {'id': 17,
'name': 'Северо-Западный федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'CITY'},
'type': 'CITY_DISTRICT'},
{'id': 98622,
'name': 'Выборгский район',
'parent': {'id': 10174,
'name': 'Санкт-Петербург и Ленинградская область',
'parent': {'id': 17,
'name': 'Северо-Западный федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'}]
Как получить на выходе примерно такую таблицу?
| id | name | type | p1_id | p1_name | p2_id | p2_name | p3_id |
|---|---|---|---|---|---|---|---|
| 11029 | Ростовская область | REPUBLIC | 26 | ЮФО | 225 | Россия | NaN |
думаю принцип понятен
Ответы (2 шт):
Автор решения: Сергей Кох
→ Ссылка
У меня получилось так, собрав исходные данные в список:
import pandas as pd
lst = [[{'id': 11029,
'name': 'Ростовская область',
'parent': {'id': 26,
'name': 'Южный федеральный округ',
'parent': {'id': 225, 'name': 'Россия', 'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'}],
[{'id': 11162,
'name': 'Свердловская область',
'parent': {'id': 52,
'name': 'Уральский федеральный округ',
'parent': {'id': 225, 'name': 'Россия', 'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'}],
[{'id': 11179,
'name': 'Белоярский',
'parent': {'id': 99994,
'name': 'Белоярский район',
'parent': {'id': 11193,
'name': 'Ханты-Мансийский автономный округ - Югра',
'parent': {'id': 52,
'name': 'Уральский федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'},
'type': 'CITY'},
{'id': 20579,
'name': 'Белоярский',
'parent': {'id': 99947,
'name': 'Белоярский городской округ',
'parent': {'id': 11162,
'name': 'Свердловская область',
'parent': {'id': 52,
'name': 'Уральский федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'},
'type': 'VILLAGE'},
{'id': 138476,
'name': 'Белоярский',
'parent': {'id': 173541,
'name': 'Белоярское сельское поселение',
'parent': {'id': 99833,
'name': 'Новобурасский район',
'parent': {'id': 11146,
'name': 'Саратовская область',
'parent': {'id': 40,
'name': 'Приволжский федеральный '
'округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'},
'type': 'OTHER'},
'type': 'VILLAGE'}],
[{'id': 20282,
'name': 'Выборгский район',
'parent': {'id': 2,
'name': 'Санкт-Петербург',
'parent': {'id': 10174,
'name': 'Санкт-Петербург и Ленинградская область',
'parent': {'id': 17,
'name': 'Северо-Западный федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'CITY'},
'type': 'CITY_DISTRICT'},
{'id': 98622,
'name': 'Выборгский район',
'parent': {'id': 10174,
'name': 'Санкт-Петербург и Ленинградская область',
'parent': {'id': 17,
'name': 'Северо-Западный федеральный округ',
'parent': {'id': 225,
'name': 'Россия',
'type': 'COUNTRY'},
'type': 'COUNTRY_DISTRICT'},
'type': 'REPUBLIC'},
'type': 'REPUBLIC_AREA'}]]
ser = pd.Series(data=lst)
df_tmp = pd.DataFrame()
# Преобразуем столбец в датафрейм с нужными столбцами
for i in range(ser.size):
df_tmp = pd.concat([df_tmp, pd.DataFrame.from_records(ser[i],
columns=['id', 'name', 'type', 'parent'])], ignore_index=True)
df = df_tmp[['id', 'name', 'type']].copy()
# запоминаем индексы не пустых строк
not_null = df_tmp[df_tmp['parent'].notna()].index
i = 1
# в цикле добавляем следующие столбцы пока 'parent' не пустой
while not not_null.empty:
# Убираем закончившиеся строки из дальнейшего расширения таблицы
df_tmp = df_tmp.dropna()
# Для работы from_records нужно сбрасывать индексы строк уже дошедшими до конца по "nan"
df_tmp = df_tmp.reset_index()
df_tmp = pd.DataFrame.from_records(df_tmp['parent'], columns=['id', 'name', 'type', 'parent'])
# Возвращаем индексы оставшихся неразобранных строк для добавления в нужное место
df_tmp = df_tmp.set_index(not_null)
df = df.join(df_tmp[['id', 'name', 'type']], rsuffix=f'_{i}')
# запоминаем индексы еще не пустых строк
not_null = df_tmp[df_tmp['parent'].notna()].index
i += 1
id name type ... id_5 name_5 type_5
0 11029 Ростовская область REPUBLIC ... NaN NaN NaN
1 11162 Свердловская область REPUBLIC ... NaN NaN NaN
2 11179 Белоярский CITY ... NaN NaN NaN
3 20579 Белоярский VILLAGE ... NaN NaN NaN
4 138476 Белоярский VILLAGE ... 225.0 Россия COUNTRY
5 20282 Выборгский район CITY_DISTRICT ... NaN NaN NaN
6 98622 Выборгский район REPUBLIC_AREA ... NaN NaN NaN
[7 rows x 18 columns]
Автор решения: Сергей Кох
→ Ссылка
Более правильное решение задачи - так как данные объекты почти JSON:
df = pd.DataFrame()
for adds in lst:
df = pd.concat([df, pd.json_normalize(adds)], ignore_index=True)