Урок по треку Python для анализа данных 7 мин

Series, DataFrame и индекс в pandas

Как устроены Series и DataFrame, роль индекса, выравнивание по меткам, типы колонок.

pandas даёт две основные структуры: Series (одна колонка с метками) и DataFrame (таблица из колонок с общим индексом). Почти все сюрпризы pandas объясняются индексом, поэтому начнём с него.

Series

Series это массив значений одного типа плюс индекс, набор меток.

import pandas as pd

s = pd.Series([120, 80, 95], index=["чай", "сок", "кофе"])
s["кофе"]        # 95, доступ по метке
s.iloc[0]        # 120, доступ по позиции
s.index          # Index(['чай', 'сок', 'кофе'])

Метки не обязаны быть уникальными. Если метка повторяется, s.loc["x"] вернёт не число, а Series из всех совпадений.

DataFrame

DataFrame удобно представлять как словарь Series с общим индексом строк. У каждой колонки свой dtype.

df = pd.DataFrame({
    "city": ["Казань", "Пермь", "Казань"],
    "revenue": [100, 250, 80],
})
df.shape        # (3, 2)
len(df)         # 3, число строк
df["revenue"]   # Series
df[["revenue"]] # DataFrame с одной колонкой

Первые шаги с новыми данными: df.shape, df.head(), df.info() (типы и непустые значения), df.describe() (статистики), df["col"].value_counts().

Выравнивание по индексу

Арифметика между Series идёт по меткам, а не по позициям:

a = pd.Series([1, 2, 3], index=["x", "y", "z"])
b = pd.Series([10, 20], index=["y", "w"])
a + b
# w     NaN
# x     NaN
# y    12.0
# z     NaN

Результат получает объединение меток, пары нет у трёх, там NaN, и тип стал float. Если отсутствующее нужно считать нулём, используйте a.add(b, fill_value=0). Если нужна именно позиционная операция, сравните .to_numpy().

То же самое происходит при присваивании колонки: df["new"] = other_series выровняет по индексу, и строки без пары получат NaN. Это частая причина «откуда пропуски после присваивания».

Типы колонок

  • int64, float64, bool: обычные числовые типы NumPy.
  • datetime64[ns], timedelta64[ns]: дата и интервал.
  • category: повторяющиеся строки, хранятся как коды плюс словарь.
  • object: произвольные объекты Python, медленно.
  • Строки: в pandas 3.0 по умолчанию строковый dtype str, в pandas 2.x был object.
  • Nullable-типы Int64, boolean, Float64: умеют хранить пропуск pd.NA, не меняя тип.

Важное следствие: обычная целочисленная колонка с пропуском превращается во float, отсюда «1.0, 2.0» в выгрузках.

pandas 3.0: Copy-on-Write

С pandas 3.0 включён Copy-on-Write. Любой объект, полученный индексацией или методом, ведёт себя как независимая копия, а реальное копирование откладывается до первой записи.

d2 = df[df["revenue"] > 90]
d2["revenue"] = 0      # меняет только d2, df не тронут

Следствие: цепочное присваивание вида df["a"][mask] = 0 больше никогда не меняет df. Менять данные нужно одним шагом через df.loc[mask, "a"] = 0. Старое предупреждение SettingWithCopyWarning ушло вместе с неоднозначностью.

Индекс: ставить или нет

set_index("user_id") полезен, когда вы часто обращаетесь по ключу, делаете join по индексу или работаете с временным рядом (DatetimeIndex даёт срезы по датам и resample). После groupby ключи сами уходят в индекс, reset_index() возвращает их в колонки, а старый индекс без имени превращается в колонку index, если не указать drop=True.

inplace

Методы с inplace=True возвращают None. Ошибка df = df.sort_values("a", inplace=True) превращает df в None. Современный стиль: без inplace, с присваиванием результата, это удобно для цепочек методов. Экономии памяти inplace обычно не даёт.

Частые ошибки

  • Ожидать сложение по позициям, а получить NaN от выравнивания.
  • Путать df["a"] (Series) и df[["a"]] (DataFrame).
  • drop("col") без columns=: ищет строку, а не колонку.
  • Присваивать результат метода с inplace=True.
  • Не проверить df.dtypes после чтения: числа оказались строками.

Что спросят на собесе

  • Чем Series отличается от DataFrame, что такое индекс?
  • Что будет при сложении двух Series с разными индексами?
  • Почему целая колонка с пропуском стала float, как этого избежать?
  • Что изменил Copy-on-Write в pandas 3.0?
  • Когда ставить set_index, а когда держать ключ колонкой?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.