Инструменты Pandas для работы с JSON

Раздел: Обработка данных -> pandas и json

Основные подходы к работе с JSON в Pandas

Как наиболее эффективно загрузить JSON данные в Pandas DataFrame?

Библиотека Pandas предоставляет встроенную функцию read_json(), которая позволяет напрямую считывать JSON из строки, файла или URL, автоматически преобразуя его в DataFrame. Это предпочтительный способ, так как он оптимизирован и обрабатывает различные ориентации данных (например, records, columns, index).

import pandas as pd

# Пример JSON строки в формате records (список словарей)
json_data = '[{"name":"Alice","age":25},{"name":"Bob","age":30}]'
df = pd.read_json(json_data)
print(df)

Pandas python json (работа с json в pandas)

    name  age
0  Alice   25
1    Bob   30

Для вложенных JSON рекомендуется использовать json_normalize() из модуля pandas.json. Эта функция распаковывает вложенные объекты в плоские таблицы.

from pandas import json_normalize

data = [
    {"id": 1, "info": {"city": "Moscow", "zip": 101000}},
    {"id": 2, "info": {"city": "SPb", "zip": 190000}}
]
df_flat = json_normalize(data, sep='_')
print(df_flat)
   id info_city  info_zip
0   1    Moscow    101000
1   2       SPb    190000

При использовании read_json() возможна ошибка ValueError, если строковый JSON не является корректным или ориентация не соответствует ожидаемой. Решение: проверить JSON валидатором (json.loads() перед передачей) и указать параметр orient явно.

Как загрузить JSON из файла с нестандартным расширением или сжатием?

Функция read_json() поддерживает сжатые файлы (gzip, bz2, xz) автоматически, если расширение соответствует. Если файл имеет другое расширение, можно указать compression.

df = pd.read_json('data.json.gz')  # автоматическое распознавание
# или явно
df = pd.read_json('data.custom', compression='gzip')

При попытке прочитать файл с неизвестным сжатием возникает ValueError: Unrecognized compression type. Решение: распаковать файл вручную перед чтением.

Каким образом обработать JSON с произвольной структурой (например, с пропусками)?

Для нерегулярных структур можно сначала прочитать всё как Python объект через json.loads(), а затем с помощью pd.json_normalize() с параметрами record_path и meta извлечь нужные вложенные списки и метаданные.

import json

raw = '{"users":[{"name":"Ivan","scores":[10,20]},{"name":"Petr","scores":[15]}],"date":"2023"}'
dict_data = json.loads(raw)
df_users = json_normalize(
    data=dict_data['users'],
    record_path='scores',         # список значений для развертывания
    meta=['name']                  # поля, остающиеся в каждой строке
)
print(df_users)
   0  name
0  10  Ivan
1  20  Ivan
2  15  Petr

Если record_path отсутствует в отдельных записях, возникнет KeyError. Решение: предусмотреть проверку наличия ключа или использовать errors='ignore' при разборе.

Как сохранить DataFrame обратно в JSON в определённом формате?

Метод to_json() позволяет экспортировать DataFrame в JSON строку или файл, выбирая ориентацию (records, columns, index, split и др.) Дополнительно можно настроить сжатие, формат дат, кодировку.

df = pd.DataFrame({'A': [1,2], 'B': [3,4]})
df.to_json('output.json', orient='records', date_format='iso')

При записи с ориентацией 'records' в файл не сохраняется информация об индексе. Если индекс важен, следует использовать 'index' или добавить его как столбец.

Расширенные примеры работы с JSON в Pandas

Чтение очень больших JSON файлов с построчной обработкой

Когда JSON содержит огромное количество записей, загрузка всего файла может привести к нехватке памяти. Можно читать файл построчно, если он представляет собой NDJSON (Newline Delimited JSON) - каждая строка - отдельный JSON объект.

Пример
import pandas as pd
import json

chunks = []
with open('large_ndjson.json', 'r') as f:
    for line in f:
        if line.strip():
            obj = json.loads(line)
            chunks.append(obj)
df = pd.DataFrame(chunks)
print(df.shape)

Для ещё большей экономии памяти применяется библиотека ijson, которая парсит поток без полной загрузки.

Пример
import ijson
import pandas as pd

records = []
with open('huge.json', 'r') as f:
    parser = ijson.parse(f)
    for prefix, event, value in parser:
        if (prefix, event) == ('item', 'map_key'):
            # настройка извлечения
            pass
# ... сборка DataFrame

Преобразование вложенных JSON с несколькими уровнями

Рассмотрим структуру с вложенными массивами объектов и метаданными на разных уровнях.

Пример
data = [
    {
        "order": 1,
        "items": [
            {"product": "phone", "qty": 1},
            {"product": "case", "qty": 2}
        ],
        "customer": {"name": "John", "loyalty": "gold"}
    },
    {
        "order": 2,
        "items": [
            {"product": "laptop", "qty": 1}
        ],
        "customer": {"name": "Jane", "loyalty": "silver"}
    }
]

df_items = json_normalize(
    data,
    record_path='items',
    meta=['order', ['customer', 'name'], ['customer', 'loyalty']]
)
print(df_items)
   product  qty  order customer.name customer.loyalty
0    phone    1      1          John             gold
1     case    2      1          John             gold
2   laptop    1      2          Jane           silver

Кастомная сериализация объектов datetime

При сохранении DataFrame с датами в JSON можно задать формат с помощью параметра date_format. Если требуется нестандартное представление, используется default_handler.

Пример
import datetime

df = pd.DataFrame({'date': [datetime.date(2024,1,1), datetime.date(2024,6,15)]})
json_str = df.to_json(orient='records', date_format='iso', default_handler=str)
print(json_str)
[{"date":"2024-01-01"},{"date":"2024-06-15"}]

Обработка JSON с пропущенными ключами и разными типами

Иногда в JSON могут отсутствовать некоторые поля или типы различаются. Через pd.json_normalize() пропуски заполняются NaN, а разные типы можно привести явно после загрузки.

Пример
json_mixed = '[{"a": 1, "b": "text"}, {"a": 2}, {"b": 3}]'
df_mixed = pd.read_json(json_mixed)
print(df_mixed.dtypes)
# a - float64, b - object
# Приведение типов
df_mixed['a'] = df_mixed['a'].astype('Int64')
df_mixed['b'] = pd.to_numeric(df_mixed['b'], errors='coerce')
print(df_mixed)
      a    b
0     1  text
1     2  NaN
2   NaN    3

Экспорт с сохранением иерархии (вложенные JSON)

Используя группировку и to_dict(), можно создать вложенный JSON из плоского DataFrame.

Пример
df = pd.DataFrame({
    'city': ['Moscow', 'Moscow', 'SPb'],
    'product': ['A', 'B', 'A'],
    'sales': [100, 200, 150]
})
result = df.groupby('city').apply(lambda x: x[['product','sales']].to_dict('records')).to_dict()
import json
print(json.dumps(result, ensure_ascii=False, indent=2))
{
  "Moscow": [
    {"product": "A", "sales": 100},
    {"product": "B", "sales": 200}
  ],
  "SPb": [
    {"product": "A", "sales": 150}
  ]
}

Работа с JSON в Pandas - comments

En
Pandas python json (python)