Преобразование глубоко вложенного JSON в Pandas кадра данных с многоиндексным иерархическим индексом на основе JSON - PullRequest
1 голос
/ 01 марта 2020

Я пытаюсь преобразовать глубоко вложенную строку json в Pandas кадр данных с иерархическим мультииндексом, основанным на иерархии в json.

Я не знаю структуру json, и это будет использоваться в списке jsons с, вероятно, будет иметь различные иерархии, так что это должно быть динамически c и не может быть жестко закодировано.

Для целей этого вопроса я использую следующее данные «Примера 2» по следующей ссылке (хотя фактические данные гораздо больше и более глубоко вложены): https://support.oneskyapp.com/hc/en-us/articles/208047697-JSON-sample-files

Я использую следующий код для интерактивного выравнивания json:

import itertools as it
import pandas as pd

def flatten_json (dictionary):

    def unpack(parent_key,parent_value):
        if isinstance (parent_value,dict):
            for key, value in parent_value.items():
                temp = parent_key + "-" + key
                print("parent_key: ", parent_key," key: ", key)
                yield temp, value
        elif isinstance(parent_value, list):
            i = 0
            for value in parent_value:
                temp2 = parent_key + "_" + str(i)
                i += 1
                yield temp2, value
        else:
            yield parent_key, parent_value
    while True:
        dictionary = dict(it.chain.from_iterable(it.starmap(unpack,dictionary.items())))

        if not any(isinstance(value,dict) for value in dictionary.values()) and not any(isinstance(value,list) for value in dictionary.values()):
            break

    return dictionary

data = ***json data from link above as a string - omitting due to length***
output_table = pd.Series(flatten_json(data)).to_frame()

Производит следующий вывод:

enter image description here

Я хочу произвести следующий вывод:

enter image description here

Ответы [ 2 ]

0 голосов
/ 01 марта 2020

Вы также можете выровнять словарь в список списков, сделать из него DataFrame, а затем установить индекс для получения требуемого вывода:

def flatten_json(dictionary):
    flattened = []

    def flatten(data, name=''):
        if type(data) is dict:
            for d in data:
                flatten(data[d], name + d + ',')
        elif type(data) is list:
            i = 0
            for l in data:
                flatten(l, name[:-1] + '_' + str(i) + ',')
                i += 1
        else:
            flattened.append((name[:-1] + ',' + data).split(','))

    flatten(dictionary)
    return flattened

list_obj=flatten_json(dict_obj)
pd.DataFrame(list_obj).set_index(list(range(len(list_obj[0])-1)))

Работает нормально для приведенного примера и менее сложно даже.

0 голосов
/ 01 марта 2020

Нашли возможное решение с некоторым воспроизведением из словаря, выводимого из оригинальной функции flatten_ json (). Не уверен, насколько это эффективно, но, похоже, это работает:

dictionary = flatten_json(data2)
all_values = list(dictionary.values())

index_list = []
for key in dictionary:
    x = tuple(key.split("-"))
    index_list.append(x)

index = pd.MultiIndex.from_tuples(index_list)

df = pd.Series(all_values, index=index).to_frame()

Любые предложения или комментарии приветствуются ...

...