Вопрос или проблема
Язык Wolfram имеет функцию Query
, которая может обходить структуры данных и применять функции на разных уровнях структуры. Я работаю со структурами JSON многомерного уровня и мне нужна функция, которая имеет аналогичную функциональность функции Query
в языке Wolfram.
Какой пакет Python и функции лучше всего воспроизводят это?
Для минимально работающего примера предположим, что у меня есть следующая структура JSON. (Экранирование строк опущено для простоты)
x = {
"Dims1":[
{
"Apple":{
"Baking":[
"Pie",
"Tart"
],
"Plant":"Tree",
"Tons":{
"2017":1.23e1,
"2018":1.12e1
}
}
},
{
"Tomato":{
"Cooking":[
"Stew",
"Sauce"
],
"Plant":"Vine",
"Tons":{
"2017":8.1,
"2018":8.3
}
}
},
{
"Banana":{
"Name":"Banana",
"Baking":[
"Bread"
],
"Cooking":[
"Fried"
],
"Plant":"Arborescent",
"Tons":{
"2017":0.8,
"2018":0.5
}
}
}
],
"Dims2":[
{
"Apple":{
"Name":"Apple",
"Baking":[
"Pie",
"Tart"
],
"Plant":"Tree",
"Tons":{
"2017":1.31e1,
"2018":1.01e1
}
}
},
{
"Sweet Potato":{
"Cooking":[
"Fried",
"Steamed"
],
"Baking":[
"Pie"
],
"Plant":"Vine",
"Tons":{
"2017":1.11e1,
"2018":1.91e1
}
}
}
]
}
В языке Wolfram я могу
a = GeneralUtilities`ToAssociations@ImportString[x, "JSON"]
<| "Dims1" -> { <|"Apple" -> <|"Baking" -> {"Pie", "Tart"}, "Plant" -> "Tree", "Tons" -> <|"2017" -> 12.3, "2018" -> 11.2|>|> |>, <|"Tomato" -> <|"Cooking" -> {"Stew", "Sauce"}, "Plant" -> "Vine", "Tons" -> <|"2017" -> 8.1, "2018" -> 8.3|>|> |>, <|"Banana" -> <|"Name" -> "Banana", "Baking" -> {"Bread"}, "Cooking" -> {"Fried"}, "Plant" -> "Arborescent", "Tons" -> <|"2017" -> 0.8, "2018" -> 0.5|>|> |> }, "Dims2" -> { <|"Apple" -> <|"Name" -> "Apple", "Baking" -> {"Pie", "Tart"}, "Plant" -> "Tree", "Tons" -> <|"2017" -> 13.1, "2018" -> 10.1|>|> |>, <|"Sweet Potato" -> <|"Cooking" -> {"Fried", "Steamed"}, "Baking" -> {"Pie"}, "Plant" -> "Vine", "Tons" -> <|"2017" -> 11.1, "2018" -> 19.1|>|> |> } |>
и затем с помощью Query
Query[All, All, All, {"Baking"}]@a
<|"Dims1" -> {<|"Apple" -> <|"Baking" -> {"Pie", "Tart"}|>|>, <|"Tomato" -> <|"Baking" -> Missing["KeyAbsent", "Baking"]|>|>, <|"Banana" -> <|"Baking" -> {"Bread"}|>|>}, "Dims2" -> {<|"Apple" -> <|"Baking" -> {"Pie", "Tart"}|>|>, <|"Sweet Potato" -> <|"Baking" -> {"Pie"}|>|>} |>
и включать функции такие как
Query[All, Join /* Flatten /* DeleteDuplicates, Values, "Baking" /* DeleteMissing]@a
<|"Dims1" -> {"Pie", "Tart", "Bread"}, "Dims2" -> {"Pie", "Tart"}|>
и
Query[All, Merge[Total] /* DateListPlot, All, "Tons",
KeyMap[DateObject[{FromDigits@#}, "Year"] &]]@a
Как это сделать с JSON в Python?
ObjectPath — это язык запросов для полуструктурированных данных, включая JSON, и имеет API для Python.
Ответ или решение
Для решения задачи извлечения данных из многослойных JSON-структур в Python можно использовать несколько подходов, аналогичных функционалу Wolfram Language Query. Наиболее подходящими инструментами для этих целей являются библиотеки, такие как pandas
, jsonpath-ng
и ObjectPath
. В этой статье мы рассмотрим, как использовать эти библиотеки для выполнения запросов, эквивалентных Wolfram Language, и проиллюстрируем это на примере указанной структуры JSON.
Пример структуры JSON
Для начала, давайте определим JSON-объект, с которым будем работать:
x = {
"Dims1": [
{
"Apple": {
"Baking": ["Pie", "Tart"],
"Plant": "Tree",
"Tons": {
"2017": 12.3,
"2018": 11.2
}
}
},
{
"Tomato": {
"Cooking": ["Stew", "Sauce"],
"Plant": "Vine",
"Tons": {
"2017": 8.1,
"2018": 8.3
}
}
},
{
"Banana": {
"Name": "Banana",
"Baking": ["Bread"],
"Cooking": ["Fried"],
"Plant": "Arborescent",
"Tons": {
"2017": 0.8,
"2018": 0.5
}
}
}
],
"Dims2": [
{
"Apple": {
"Name": "Apple",
"Baking": ["Pie", "Tart"],
"Plant": "Tree",
"Tons": {
"2017": 13.1,
"2018": 10.1
}
}
},
{
"Sweet Potato": {
"Cooking": ["Fried", "Steamed"],
"Baking": ["Pie"],
"Plant": "Vine",
"Tons": {
"2017": 11.1,
"2018": 19.1
}
}
}
]
}
Использование pandas
Библиотека pandas
предоставляет мощные средства для обработки данных и позволяет проводить выборки из сложных структур. Для извлечения данных из вышеуказанного JSON можно воспользоваться следующими шагами:
- Установите библиотеку
pandas
, если она еще не установлена:
pip install pandas
- Преобразуйте JSON в DataFrame и выполните выборку:
import pandas as pd
# Преобразование JSON в DataFrame
df_dims1 = pd.json_normalize(x['Dims1'])
df_dims2 = pd.json_normalize(x['Dims2'])
# Объединение и выполнение выборки
combined_df = pd.concat([df_dims1, df_dims2], keys=['Dims1', 'Dims2'])
# Извлечение данных по ключу "Baking"
baking_items = combined_df.apply(lambda row: row['Apple'].get('Baking', None), axis=1).dropna()
print(baking_items)
Использование jsonpath-ng
jsonpath-ng
— это библиотека для выполнения запросов к JSON-структуре по подобию XPath для XML. Чтобы использовать эту библиотеку, выполните следующие шаги:
- Установите
jsonpath-ng
:
pip install jsonpath-ng
- Используйте jsonpath для извлечения данных:
from jsonpath_ng import jsonpath, parse
jsonpath_expr = parse('$.Dims1[*].Apple.Baking')
baking_items = [match.value for match in jsonpath_expr.find(x)]
print(baking_items)
Использование ObjectPath
ObjectPath
— это еще одна библиотека для работы с полуструктурированными данными, такой как JSON, с интересным и простым синтаксисом для запросов.
- Установите ObjectPath:
pip install objectpath
- Выполните запрос:
import objectpath
# Создание базы данных на основе JSON
generator = objectpath.ObjectPath(x)
# Выполнение запроса к БД
baking_items = generator.execute('$..Baking')
print(baking_items)
Заключение
Вышеописанные подходы предоставляют гибкие возможности для работы с многослойными JSON-структурами в Python. Каждая библиотека предлагает уникальные функции, и выбор зависит от ваших предпочтений и задач. Библиотека pandas
отлично подходит для обработки табличных данных, в то время как jsonpath-ng
и ObjectPath
позволяют более интуитивно работать с вложенными структурами. Определите наиболее подходящий вариант для вашей задачи, исследуя функционал каждой библиотеки.