Преобразовать вложенный словарь в 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)
→ Ссылка