Python Pandas для сравнения двух JSON, их общего подмножества и выявления различий

Я пытаюсь написать код на Python, используя Python Pandas, чтобы сравнить два json на основе данных, представленных во втором json, т.е. вернуть true или false на основе следующей логики:

  1. Сначала проверьте, существует ли json, предоставленный во втором json, и
  2. Если он существует, проверьте, соответствует ли значение, указанное во втором json, в первом json.
  3. Если ключ не существует, сообщите о ключе и продолжите проверку оставшихся ключей и сообщите обо всех ключах.

Первый Json:

{
    "header": {
        "chef":"Gordan",
        "restaurants":"petrus"
    },
    "menu":[
        {
            "starters":{
                "Isle of skye scallop":"Coastal herbs, lemon, olive oil",
                "Native Lobster":"Anjou pear, walnuts",
                "Smoked Eel":"Oscietra caviar, celeriac, apple"
            },
            "main":{
                "Cornish cod":"Heirloom carrots, pomelo",
                "Anjou Pigeon":"Beetroot, cranberry, red amaranth"
            }
        }
    ]

}

Второй json:

{
    "header": {
        "chef":"Gordan"
    },
    "menu":[
        {
            "starters":{
                "Isle of skye scallop":"Coastal herbs, lemon, olive oil"
            },
            "main":{
                "Cornish cod":"Heirloom carrots, pomelo"
            }
        }
    ]
}

Код который я написал и не работает

import pandas as pd
import json

# First JSON
first_json = {
    "header": {
        "chef":"Gordan",
        "restaurants":"petrus"
    },
    "menu":[
        {
            "starters":{
                "Isle of skye scallop":"Coastal herbs, lemon, olive oil",
                "Native Lobster":"Anjou pear, walnuts",
                "Smoked Eel":"Oscietra caviar, celeriac, apple"
            },
            "main":{
                "Cornish cod":"Heirloom carrots, pomelo",
                "Anjou Pigeon":"Beetroot, cranberry, red amaranth"
            }
        }
    ]
}

# Second JSON
second_json = {
    "header": {
        "chef":"Gordan"
    },
    "menu":[
        {
            "starters":{
                "Isle of skye scallop":"Coastal herbs, lemon, olive oil"
            },
            "main":{
                "Cornish cod":"Heirloom carrots, pomelo"
            }
        }
    ]
}

# Convert the JSONs to pandas DataFrames
first_df = pd.json_normalize(first_json)
second_df = pd.json_normalize(second_json)

# Check if the second JSON exists in the first JSON
if second_df.isin(first_df).all().all():
    print("Second JSON exists in the first JSON.")
else:
    print("Second JSON does not exist in the first JSON.")

Вывод: второй JSON не существует в первом JSON.

ПРИМЕЧАНИЕ. В основном я рассматриваю преобразование обоих фреймов данных, а затем подгруппу обоих фреймов данных по отношению ко второму фрейму данных, поскольку он меньше (с использованием имен столбцов), а затем сравнивает столбец за столбцом и передает отчеты в случай равен или не соответствует сообщению о том, какие поля не совпадают.

Похоже, jsondiff или jsonpatch могли бы помочь вам вместо панд?

jqurious 29.03.2023 20:40

Спасибо @jqurious - я использовал JSON для этого вопроса, однако json, с которым я имею дело, довольно велик, и я также ищу масштабируемое решение, если трафик транзакций значительно возрастет. Кроме того, это звучит как типичный вариант использования панд.

JavaMan 29.03.2023 21:05
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Код ниже работает:

import pandas as pd
from pandas.io.json import json_normalize
import warnings


def flatten_json(y):
    out = {}

    def flatten(x, name=''):
        if type(x) is dict:
            for a in x:
                flatten(x[a], name + a + '.')
        elif type(x) is list:
            i = 0
            for a in x:
                flatten(a, name + str(i) + '.')
                i += 1
        else:
            out[name[:-1]] = x

    flatten(y)
    return out


def check_common_columns(df1, df2):
    # convert nested JSON data to flat format
    with warnings.catch_warnings():
        warnings.simplefilter(action='ignore', category=FutureWarning)
        df1 = json_normalize(flatten_json(df1))
        df2 = json_normalize(flatten_json(df2))

    # get common columns
    common_cols = set(df1.columns) & set(df2.columns)

    # suppress FutureWarning for passing set as an indexer
    with warnings.catch_warnings():
        warnings.simplefilter(action='ignore', category=FutureWarning)
        df1_common = df1[list(common_cols)]
        df2_common = df2[list(common_cols)]

    # get rows with common columns that have different values
    diff_idx = (df1_common != df2_common).any(axis=1)
    df_diff = pd.concat([df1_common, df2_common])[diff_idx].drop_duplicates()

    # extract column names with different values
    col_names = list(df_diff.columns[df_diff.apply(pd.Series.nunique) > 1])

    return col_names, df_diff[col_names]


# Example JSONs
json1 = {
    "header": {
        "chef": "Gordon",
        "restaurant": "Hell's Kitchen"
    },
    "menu": [
        {
            "starters": {
                "Starter1": "Coastal herbs, lemon, olive oil",
                "Starter2": "Anjou pear, walnuts",
                "Starter3": "Oscietra caviar, celeriac, apple"
            },
            "main": {
                "main1": "Heirloom carrots, pomelo",
                "main2": "Beetroot, cranberry, red amaranth"
            }
        }
    ]
}

json2 = {
    "header": {
        "chef": "Bobby",
        "restaurant": "Bobby's Kitchen"
    },
    "menu": [
        {
            "starters": {
                "Starter1": "Coastal herbs, lemon, olive oil",
                "Starter2": "Anjou pear, walnuts",
                "Starter3": "Oscietra caviar, celeriac, apple"
            },
            "main": {
                "main1": "Heirloom carrots, pomelo",
                "main2": "Beetroot, cranberry, spinach"
            }
        }
    ]
}

col_names, diff_df = check_common_columns(json1, json2)

print("Columns with different values: ")
print(col_names)
print("\nDataframe with different values: ")
print(diff_df)

Выход

UserWarning: Boolean Series key will be reindexed to match DataFrame index.
  df_diff = pd.concat([df1_common, df2_common])[diff_idx].drop_duplicates()
Columns with different values: 
['header.restaurant', 'menu.0.main.main2', 'header.chef']

Dataframe with different values: 
  header.restaurant                  menu.0.main.main2 header.chef
0    Hell's Kitchen  Beetroot, cranberry, red amaranth      Gordon
0   Bobby's Kitchen       Beetroot, cranberry, spinach       Bobby

Другие вопросы по теме