#python #json #pandas
#python #json #pandas
Вопрос:
Я пытаюсь разобрать JSON в фрейм данных pandas
Вот мой json:
In [1]: data
Out[1]:
[
{
"field_1": {
"key1": value1,
"key2": value2
},
"field_2": {
"key1": value3,
"key2": value4
},
"data_A": [
{
"key1": value5,
"key2": value6
},
{
"key1": value7,
"key2": value8
}
]
"data_B": [
{
"key1": value9,
"key2": value10
}
]
},
{
"field_1": {
"key1": value11,
"key2": value12
},
"field_2": {
"key1": value13,
"key2": value14
},
"data_B": [
{
"key1": value15,
"key2": value16
},
{
"key1": value17,
"key2": value18
}
]
},
...
]
Как вы можете видеть, каждый мой объект в data
содержит field_1 и field_2. Он также содержит либо data_A, либо data_B (по крайней мере, один из двух). data_A, когда он существует, представляет собой список из одного или нескольких элементов, а data_B, когда он существует, представляет собой список из одного или нескольких элементов.
Чего бы я хотел, так это следующего результата:
In [2]: df_A
Out[2]:
data_A.key1 data_A.key2 field_1.key_1 field_1.key_2 field_2.key_1 field_2.key_2
0 value5 value6 value1 value2 value3 value4
1 value7 value8 value1 value2 value3 value3
...
In [3]: df_B
Out[3]:
data_B.key1 data_B.key2 field_1.key_1 field_1.key_2 field_2.key_1 field_2.key_2
0 value9 value10 value1 value2 value3 value4
1 value15 value16 value11 value12 value13 value14
2 value17 value18 value11 value12 value13 value14
...
Я могу сделать это с помощью циклов for, но есть ли более эффективный и элегантный способ?
Ответ №1:
Если вы используете Linux или Mac с Python 3.6 , вы можете использовать библиотеку (bamboo), которую я написал для преобразования вложенных данных (например, JSON) в Pandas. Если вы работаете в Windows или используете другую версию Python, но все еще заинтересованы в библиотеке, дайте мне знать, и я посмотрю, смогу ли я создать более переносимую версию.
Вы можете установить bamboo из pypi: pip install bamboo-nested
Преобразование полностью выполняется в расширении C и numpy, поэтому оно должно быть очень производительным.
Вот как это будет работать с предоставленным вами JSON (я внес несколько небольших изменений, чтобы сделать его допустимым примером JSON):
s = '''
[
{
"field_1": {
"key1": "value1",
"key2": "value2"
},
"field_2": {
"key1": "value3",
"key2": "value4"
},
"data_A": [
{
"key1": "value5",
"key2": "value6"
},
{
"key1": "value7",
"key2": "value8"
}
],
"data_B": [
{
"key1": "value9",
"key2": "value10"
}
]
},
{
"field_1": {
"key1": "value11",
"key2": "value12"
},
"field_2": {
"key1": "value13",
"key2": "value14"
},
"data_B": [
{
"key1": "value15",
"key2": "value16"
},
{
"key1": "value17",
"key2": "value18"
}
]
}
]
'''
from bamboo import from_json
tree = from_json(s)
df_A = tree.flatten(exclude=[tree.data_B]) # you can also refer to pieces of the tree with string names, i.e. "exclude=['data_B']"
df_B = tree.flatten(exclude=[tree.data_A])
print(df_A)
print(df_B)
Полученный результат является:
data_A_key1 data_A_key2 field_1_key1 field_1_key2 field_2_key1 field_2_key2
0 value5 value6 value1 value2 value3 value4
1 value7 value8 value1 value2 value3 value4
data_B_key1 data_B_key2 field_1_key1 field_1_key2 field_2_key1 field_2_key2
0 value9 value10 value1 value2 value3 value4
1 value15 value16 value11 value12 value13 value14
2 value17 value18 value11 value12 value13 value14
Это не совсем то, что вы просили, но очень близко (по умолчанию для создания имен столбцов используются символы подчеркивания). Вы можете изменить название столбца, передав другое в параметр «name_strategy» параметра «flatten». В настоящее время у меня нет возможности изменить разделитель имен столбцов по умолчанию, но я могу добавить это.
Я надеюсь, это поможет!
Комментарии:
1. Вы также можете использовать Pandas напрямую, чтобы получить нечто подобное, но вы должны быть очень конкретны в отношении столбцов, которые вы хотите включить. Вам также понадобятся пустые значения для отсутствующих ключей (например, «data_A»: [] во второй записи).
print(json_normalize(json.loads(s), 'data_B', [['field_1', 'key1'], ['field_1', 'key2'], ['field_2', 'key1'], ['field_2', 'key2']])) print(json_normalize(json.loads(s), 'data_A', [['field_1', 'key1'], ['field_1', 'key2'], ['field_2', 'key1'], ['field_2', 'key2']]))
bamboo должен быть быстрее и проще для изучения данных, но, возможно, подхода Pandas достаточно.