PandasSeniorSystem design

Каковы улучшения производительности в Pandas 2.0 (Arrow-backed dtypes, Copy-on-Write)?

Pandas 2.0 добавил Arrow-backed dtypes (меньше памяти, nullable int без float, zero-copy I/O) и Copy-on-Write (CoW), устраняющий SettingWithCopyWarning и делающий поведение срезов детерминированным.

Arrow-backed dtypes в Pandas 2.0

Pandas 2.0 ввёл нативную поддержку Apache Arrow как backend для хранения данных. Столбцы можно создать с Arrow-типом, передав суффикс [pyarrow] в параметр dtype или используя dtype_backend="pyarrow" при чтении файлов.

import pandas as pd
import pyarrow as pa

# Создание DataFrame с Arrow-backed типами
df = pd.DataFrame(
    {"id": [1, 2, 3], "name": ["Alice", "Bob", None], "score": [9.5, 8.0, 7.2]},
    dtype="ArrowDtype"
)

# Явное указание Arrow-типов
df2 = pd.DataFrame({
    "id": pd.array([1, 2, 3], dtype="int32[pyarrow]"),
    "name": pd.array(["Alice", "Bob", None], dtype="string[pyarrow]"),
})

# При чтении Parquet/CSV с backend=pyarrow
df3 = pd.read_parquet("data.parquet", dtype_backend="pyarrow")
df4 = pd.read_csv("data.csv", dtype_backend="pyarrow")

print(df2.dtypes)
# id      int32[pyarrow]
# name    string[pyarrow]

Что даёт Arrow backend

  • Nullable integer/boolean без конвертации в float: int64[pyarrow] хранит NA нативно, а не как NaN в float64.
  • Меньший расход памяти: Arrow использует буферы с битовыми масками для null-значений вместо sentinel-значений NumPy.
  • Ускорение I/O: чтение Parquet через dtype_backend="pyarrow" даёт zero-copy, когда данные уже в Arrow-формате.
  • Поддержка вложенных типов: list[pyarrow], struct[pyarrow], map[pyarrow] — типы, которые NumPy не поддерживает.

Copy-on-Write (CoW)

До Pandas 2.0 изменение среза DataFrame иногда модифицировало оригинал, иногда нет — поведение зависело от того, возвращает ли операция view или копию. Pandas 2.0 вводит Copy-on-Write: любой объект (DataFrame или Series), полученный из другого, считается независимым — данные копируются только в момент первой записи.

import pandas as pd

# Включение CoW (обязательно в pandas 2.x, default в pandas 3.0)
pd.options.mode.copy_on_write = True

df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
slice_df = df[["a"]]   # view, данные не копируются

slice_df["a"] = 99     # здесь происходит копирование (write)
print(df["a"].tolist())   # [1, 2, 3] — оригинал не тронут
print(slice_df["a"].tolist())  # [99, 99, 99]

Практические выгоды CoW

  • Устранение SettingWithCopyWarning — самого частого источника путаницы.
  • Снижение ненужных копий: Pandas 2.0 откладывает копирование до реального изменения, что уменьшает пиковое потребление памяти в цепочках трансформаций.
  • Детерминированное поведение: код работает предсказуемо вне зависимости от того, view или copy возвращает конкретная операция.

Миграция на CoW

# Включить предупреждения о будущих изменениях
pd.options.mode.copy_on_write = "warn"  # pandas 2.x

# Найти устаревшие паттерны: chained assignment
df[df["a"] > 1]["b"] = 0  # будет предупреждение

# Правильный вариант
df.loc[df["a"] > 1, "b"] = 0

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

  • CoW не включён по умолчанию в Pandas 2.x — нужно явно установить pd.options.mode.copy_on_write = True; в Pandas 3.0 это станет дефолтом.
  • Arrow backend требует установки pyarrow: pip install pyarrow, он не входит в базовую зависимость Pandas.
  • Не все операции поддерживают Arrow-типы: некоторые NumPy-зависимые функции (например, np.where напрямую) могут вернуть NumPy-массив, что приведёт к потере Arrow-типа.
  • Смешение NumPy и Arrow столбцов в одном DataFrame — законно, но может замедлить операции из-за implicit конвертаций.
  • Chained assignment всё ещё опасен без CoW: df[mask]["col"] = val молча ничего не делает при CoW — правильно использовать df.loc[mask, "col"] = val.
  • Производительность Arrow неоднородна: Arrow быстрее для string/nested типов и I/O, но для тяжёлых числовых операций NumPy backend может оказаться быстрее из-за оптимизаций BLAS/LAPACK.
  • Nullable pd.NA vs float NaN: Arrow-столбцы возвращают pd.NA, а не np.nan, что ломает код, проверяющий x != x или math.isnan(x).
  • Сериализация в pickle: Arrow-backed DataFrame сериализуется иначе — не совместим с pickle-файлами, записанными в Pandas 1.x.

Common mistakes

  • Объяснять pandas 2 performance только синтаксисом без shape, dtype, состояния или режима выполнения.
  • Игнорировать leakage, воспроизводимость, пустые входы и скрытые копии данных.
  • Не проверять production-симптомы: latency, память, ретраи, дрейф качества и несовпадение версий.

What the interviewer is testing

  • Может ли связать pandas 2 performance с реальным контрактом входов и выходов.
  • Упоминает ли тесты, метрики, reproducibility и диагностику ошибок.
  • Видит ли различие между demo-кодом в ноутбуке и production-пайплайном.
  • Предлагает ли observability, rollback, ограничения стоимости и стратегию incident replay.

Sources

Related topics