Я хочу сгладить следующий JSON на каждом уровне и создать фрейм данных pandas для каждого уровня, я использую flatten_json
для этого, но для этого мне нужно пройти через каждый уровень, который создает несколько вложенных циклов for:
{
"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 (сгладить JSON в 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? Уровни могут понижаться на несколько уровней. Я пробовал использовать для этого json_normalize
, но мне также нужны идентификаторы родительского уровня в окончательном выводе, а json_normalize
не работает с несколькими путями записи.
1 ответ
Я решил это с помощью рекурсии, вот мой код:
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
Похожие вопросы
Связанные вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.