Собесов

Сценарий: уменьшить размер датафрейма в RAM в 5 раз

PythonOptimisation и big dataСредняяMiddle

Условие

DataFrame занимает 8 ГБ. Менеджер выдал машину на 16 ГБ, но нужно ещё join со справочником на 4 ГБ. Как уменьшить df, не теряя данные?

Решение

Шаг 1: измерить

df.info(memory_usage='deep')
df.memory_usage(deep=True).sort_values(ascending=False)

deep=True обязателен для object-колонок — иначе показывает только размер указателей.

Шаг 2: downcast чисел

import pandas as pd
 
for c in df.select_dtypes('integer').columns:
    df[c] = pd.to_numeric(df[c], downcast='integer')   # int64 → int8/16/32
 
for c in df.select_dtypes('float').columns:
    df[c] = pd.to_numeric(df[c], downcast='float')     # float64 → float32

Шаг 3: category для строк с низкой кардинальностью

for c in df.select_dtypes('object').columns:
    if df[c].nunique() / len(df) < 0.5:
        df[c] = df[c].astype('category')

category хранит уникальные значения один раз + int-коды → строка «active»/«inactive» в 100M строк = ~100 МБ вместо ~6 ГБ.

Шаг 4: pyarrow backend (pandas 2.0+)

df = df.convert_dtypes(dtype_backend='pyarrow')

PyArrow строки компактнее object на 30-70%, и read_parquet быстрее.

Шаг 5: сбросить ненужные колонки рано

df = pd.read_parquet('events.parquet', columns=['user_id', 'amount', 'country'])

Чтение columns= — самая дешёвая оптимизация.

Подводные камни

  1. float32 теряет точность — для денег, координат, ML-фичей оставлять float64.
  2. category + int после merge может неожиданно стать object. Проверять dtype после операций.
  3. Int8 (nullable) хорошо, но в groupby медленнее обычного int — баланс памяти и скорости.
  4. convert_dtypes(dtype_backend='pyarrow') не всё поддерживает (некоторые операции падают) — тестировать на куске.
  5. Если df всё равно не лезет — переходить на чанки/polars/Dask, downcast не панацея.

Эталонный ответ

memory_usage(deep=True) → downcast чисел pd.to_numeric(downcast=) → строки в categorycolumns= при чтении → опционально dtype_backend='pyarrow'. Это даёт обычно 3-10× экономии.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти