PandasMiddleExperience

Какие ключевые абстракции Pandas нужно понимать, чтобы не получать формально рабочие, но неверные результаты?

Ключевые абстракции Pandas: выравнивание по Index (не по позиции), семантика view/copy с SettingWithCopyWarning, неявная конвертация dtype, порядок строк в GroupBy и тихое дублирование при merge без validate.

Ключевые абстракции Pandas

Pandas строится на нескольких концептах, непонимание которых порождает формально работающий, но семантически неверный код.

1. Index и выравнивание по оси

В отличие от NumPy, операции между двумя Series/DataFrame выравниваются по Index, а не по позиции. Это часто приводит к неожиданным NaN.

import pandas as pd

a = pd.Series([1, 2, 3], index=[0, 1, 2])
b = pd.Series([10, 20, 30], index=[1, 2, 3])  # сдвинутый индекс

print(a + b)
# 0     NaN   ← index=0 есть только в a
# 1    12.0
# 2    22.0
# 3     NaN   ← index=3 есть только в b

Решение: a.values + b.values (NumPy-массивы без индекса) или явный reset_index.

2. View vs Copy — SettingWithCopyWarning

Pandas не гарантирует, возвращает ли операция view (вид на исходные данные) или copy (новый объект). Мутация view меняет оригинал; мутация copy — нет.

df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})

# НЕВЕРНО — может не изменить df, SettingWithCopyWarning
subset = df[df["a"] > 1]
subset["b"] = 99  # может быть copy, df не изменится

# ВЕРНО — явная копия или .loc
subset = df[df["a"] > 1].copy()
subset["b"] = 99  # безопасно

# или через .loc на оригинальном df
df.loc[df["a"] > 1, "b"] = 99

В Pandas 2.x включён Copy-on-Write (CoW) по умолчанию — поведение стало предсказуемее, но старый код может сломаться.

3. dtype и скрытые преобразования

При чтении CSV Pandas выводит dtype эвристически. NaN в целочисленной колонке конвертирует её в float64, что ломает join-ы по ключу.

df = pd.read_csv("orders.csv", dtype={"user_id": "Int64"})  # nullable integer
print(df.dtypes)
# user_id    Int64  ← сохраняет NaN без float-конвертации

4. GroupBy — split-apply-combine и порядок строк

После groupby/apply порядок строк может измениться. Если следующий шаг зависит от порядка (например, lag/shift по времени), результат будет неверным без явной сортировки.

df = pd.DataFrame({
    "user": [1, 1, 2, 2],
    "date": pd.to_datetime(["2025-01-02", "2025-01-01", "2025-01-03", "2025-01-01"]),
    "amount": [100, 200, 50, 150],
})

# НЕВЕРНО — shift без сортировки даёт lag на неверных строках
df["prev"] = df.groupby("user")["amount"].shift(1)

# ВЕРНО — сначала сортировка внутри группы
df = df.sort_values(["user", "date"])
df["prev"] = df.groupby("user")["amount"].shift(1)

5. merge — тип join-а и дублирование строк

По умолчанию pd.merge() делает inner join и не предупреждает, если один ключ встречается несколько раз — строки молча дублируются (cartesian product).

# Явная валидация: ключ уникален в правой таблице
result = pd.merge(
    orders, users,
    on="user_id",
    how="left",
    validate="many_to_one",  # выбросит MergeError при дублях
)

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

  • Выравнивание по Index — операции между DataFrame с разными индексами порождают NaN без предупреждений
  • SettingWithCopyWarning — игнорирование этого предупреждения приводит к скрытым мутациям или их отсутствию
  • Смешение .loc (label-based) и .iloc (position-based) при нецелочисленном индексе даёт разные строки
  • apply() с lambda возвращает Series или DataFrame в зависимости от формы — shape выхода непредсказуем без явного result_type
  • inplace=True не гарантирует отсутствие копии и не даёт выигрыша по памяти в большинстве случаев
  • read_csv без explicit dtype — тихая конвертация типов, особенно опасна для ID-колонок с ведущими нулями (телефоны, коды)
  • pivot_table молча агрегирует дубли через aggfunc=mean, если не указано иное — данные теряются без ошибки

What hurts your answer

  • Знать термины Pandas, но не понимать связи между абстракциями
  • Объяснять поведение через отдельные примеры вместо причинной модели
  • Не связывать mental model с диагностикой ошибок

What they're listening for

  • Понимает ключевые абстракции Pandas
  • Может предсказывать поведение системы через mental model
  • Связывает модель с debugging и production decisions

Related topics