Как получить доступ к определенным данным во вложенном файле JSON с помощью Python и Pandas

Я все еще новичок в Python и работаю над своим первым REST API. У меня есть файл JSON с несколькими уровнями. Когда я создаю фрейм данных с пандами, что бы я ни пытался, я не могу получить доступ к нужному мне уровню.

API построен с помощью Flask и имеет правильные параметры для книги, главы и стиха.

Ниже приведен небольшой пример данных JSON.

{
  "book": "Python",
  "chapters": [
    {
      "chapter": "1",
      "verses": [
        {
          "verse": "1",
          "text": "Testing"
        },
        {
          "verse": "2",
          "text": "Testing 2"
        }
      ]
    }
  ]
}

Вот мой код:

@app.route("/api/v1/<book>/<chapter>/<verse>/")
def api(book, chapter, verse):
    book = book.replace(" ", "").title()

    df = pd.read_json(f"Python/{book}.json")

    filt = (df['chapters']['chapter'] == chapter) & (df['chapters']['verses']['verse'] == verse)
    text = df.loc[filt].to_json()

    result_dictionary = {'Book': book, 'Chapter': chapter, "Verse": verse, "Text": text}
    return result_dictionary

Вот ошибка, которую я получаю:

KeyError
KeyError: 'chapter'

Я попытался нормализовать данные, используя df.loc для фильтрации и просто пытаясь получить доступ к данным напрямую.

Ожидается, что конечная точка API позволит пользователю указать книгу, главу и стих в качестве аргументов, а затем вернет текст для данной позиции на основе этих предоставленных параметров.

Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
Учебник по веб-скрапингу
Учебник по веб-скрапингу
Привет, ребята... В этот раз мы поговорим о веб-скрейпинге. Целью этого обсуждения будет узнать и понять, что такое веб-скрейпинг, а также узнать, как...
Тонкая настройка GPT-3 с помощью Anaconda
Тонкая настройка GPT-3 с помощью Anaconda
Зарегистрируйте аккаунт Open ai, а затем получите ключ API ниже.
0
0
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы пытаетесь получить доступ к списку в dict с помощью ключа dict?

Получит результат. Но df.loc[filt] требует список с (булевыми) фильтрами, а выше генерирует только одно значение false или true, поэтому вы не можете фильтровать его.

Вы можете фильтровать как:

df.from_dict(df['chapters'][0]['verses']).query("verse =='1'")
Ответ принят как подходящий

Вы можете сначала создать фрейм данных JSON, а затем запросить его.

import json
import pandas as pd

def api(book, chapter, verse):
    # Read the JSON file
    with open(f"Python/{book}.json", "r") as f:
        data = json.load(f)

    # Convert it into a DataFrame
    df = pd.json_normalize(data, record_path=["chapters", "verses"], meta=["book", ["chapters", "chapter"]])
    df.columns = ["Verse", "Text", "Book", "Chapter"]  # rename columns

    # Query the required content
    query = f"Book == '{book}' and Chapter == '{chapter}' and Verse == '{verse}'"
    result = df.query(query).to_dict(orient = "records")[0]

    return result

Здесь df будет выглядеть так после json_normalize:

  Verse       Text    Book Chapter
0     1    Testing  Python       1
1     2  Testing 2  Python       1
2     1    Testing  Python       2
3     2  Testing 2  Python       2

А result это:

{'Verse': '2', 'Text': 'Testing 2', 'Book': 'Python', 'Chapter': '1'}

Это сработало отлично. Спасибо. Я еще не проверял другие ответы, но я тоже их проверю. Спасибо всем. Люблю сообщество Python.

AzulaFire 18.02.2023 09:33

Одна из проблем здесь в том, что "chapters" — это список

"chapters": [

Вот почему ["chapters"]["chapter"] не будет работать так, как вы хотите.

Если вы новичок в этом, может быть полезно «нормализовать» данные самостоятельно:

import json

with open("book.json") as f:
    book = json.load(f)

for chapter in book["chapters"]:
    for verse in chapter["verses"]:
        row = book["book"], chapter["chapter"], verse["verse"], verse["text"]
        print(repr(row))
('Python', '1', '1', 'Testing')
('Python', '1', '2', 'Testing 2')

Это можно передать pd.DataFrame()

df = pd.DataFrame(
    ([book["book"], chapter["chapter"], verse["verse"], verse["text"]]
        for verse in chapter["verses"] 
        for chapter in book["chapters"]),
    columns=["Book", "Chapter", "Verse", "Text"]
)
     Book Chapter Verse       Text
0  Python       1     1    Testing
1  Python       1     2  Testing 2

Хотя неясно, нужен ли вам вообще здесь датафрейм.

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