flatten_ json функция рекурсивного выравнивания для списков - PullRequest
0 голосов
/ 15 апреля 2020

Я хочу сгладить следующее JSON на каждом уровне и создать pandas фрейм данных для уровня, я использую flatten_json, чтобы сделать это, но для этого мне нужно l oop через каждый уровень, который создает несколько вложенных для циклов:

{
"metadata": {
    "name": "abc",
    "time": "2020-04-01"
},
"data": [
    {
        "identifiers": [
            {
                "type": "abc",
                "scheme": "def",
                "value": "123"
            },
            {
                "type": "abc",
                "scheme": "def",
                "value": "123"
            }
        ],
        "name": "qwer",
        "type": "abd",
        "level1": [
            {
                "identifiers": [
                    {
                        "type": "abc",
                        "scheme": "def",
                        "value": "123"
                    },
                    {
                        "type": "abc",
                        "scheme": "def",
                        "value": "123"
                    }
                ],
                "name": "asd",
                "type": "abd",
                "level2": [
                    {
                        "identifiers": [
                            {
                                "type": "abc",
                                "scheme": "def",
                                "value": "123"
                            },
                            {
                                "type": "abc",
                                "scheme": "def",
                                "value": "123"
                            }
                        ],
                        "name": "abs",
                        "type": "abd"
                    },
                    {
                        "identifiers": [
                            {
                                "type": "abc",
                                "scheme": "def",
                                "value": "123"
                            },
                            {
                                "type": "abc",
                                "scheme": "def",
                                "value": "123"
                            }
                        ],
                        "name": "abs",
                        "type": "abd"
                    }
                ]
            }
        ]
    }
]
}

Я пытаюсь сгладить это json, используя flatten_ json ( Flatten JSON in Python), используя следующий код:

import pandas as pd
import flatten_json as fj
import json

level2 = []
keys = {'data', 'level1', 'level2'}

with open('test_lh.json') as f:
    data = json.load(f)

for x in data['data']:
    for y in x['level1']:
        for z in y['level2']:
            dic = fj.flatten(z)
            level2.append(dic)

df = pd.DataFrame(level2)
print(df)

Вывод, приведенный ниже:

      identifiers_0_type identifiers_0_scheme identifiers_0_value identifiers_1_type identifiers_1_scheme identifiers_1_value name type
0                abc                  def                 123                abc                  def                 123  abs  abd
1                abc                  def                 123                abc                  def                 123  abs  abd

Как бы я написал рекурсивную функцию для получения того же вывода без вызова n числа циклов for? Уровни могут go упасть на несколько уровней. Я попытался использовать json_normalize для этого, но мне также нужны идентификаторы родительского уровня в конечном выводе, а json_normalize не работает с несколькими путями записи.

1 Ответ

0 голосов
/ 15 апреля 2020

Я решил это с помощью рекурсии, вот мой код:

import json
import pandas as pd
import flatten_json as fj

keys = {'data', 'level1', 'level2', 'level3'}
with open('test_lh.json') as f:
    data = json.load(f)

levels = ['data.level1.level2.level3', 'data.level1.level2', 'data.level1', 'data']
recs_dict = {}

def do_step(data_dict, level, depth, path):
    recs = []
    for x in data_dict[level]:
        if depth < len(path.split('.'))-1:
            do_step(x, path.split('.')[depth+1], depth+1, path)
        else:
            dic = fj.flatten(x, root_keys_to_ignore=keys)
            recs.append(dic)
    recs_dict[level] = recs

for path in levels:
    do_step(data, path.split('.')[0], 0, path)

for key, value in recs_dict.items():
    print(key)
    df = pd.DataFrame(recs_dict[key])
    print(df)

А вот вывод:

level3
  identifiers_0_type identifiers_0_scheme identifiers_0_value identifiers_1_type identifiers_1_scheme identifiers_1_value name    type
0                abc                  def                 123                abc                  def                 123  abs  level3
1                abc                  def                 123                abc                  def                 123  abs  level3
level2
  identifiers_0_type identifiers_0_scheme identifiers_0_value identifiers_1_type identifiers_1_scheme identifiers_1_value name    type
0                abc                  def                 123                abc                  def                 123  abs  level2
1                abc                  def                 123                abc                  def                 123  abs     abd
level1
  identifiers_0_type identifiers_0_scheme identifiers_0_value identifiers_1_type identifiers_1_scheme identifiers_1_value name    type
0                abc                  def                 123                abc                  def                 123  asd  level1
data
  identifiers_0_type identifiers_0_scheme identifiers_0_value identifiers_1_type identifiers_1_scheme identifiers_1_value  name type
0                abc                  def                 123                abc                  def                 123  qwer  abd
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...