Нашли ошибку?
среднийpandas 3.0.6

Сводные таблицы: pivot_table, crosstab

Сводная таблица как в Excel — итоги по двум измерениям сразу, с итоговыми строкой и столбцом.

Нужно знать:agg и именованная агрегация

Содержание статьи

Коротко

  • pivot_table(values, index, columns, aggfunc) — значения из index становятся строками, из columns — столбцами, в ячейках — итог aggfunc.
  • По умолчанию aggfunc="mean" — для сумм укажите "sum" явно.
  • fill_value=0 заполняет пустые сочетания, margins=True добавляет итоговые строку и столбец.
  • index и columns могут быть списками — получится MultiIndex.
  • pd.crosstab(a, b) — таблица частот: сколько строк в каждом сочетании; normalize — доли.

Синтаксис

df.pivot_table(values=None, index=None, columns=None, aggfunc="mean",
             fill_value=None, margins=False, margins_name="All", observed=True)
pd.crosstab(index, columns, values=None, aggfunc=None, normalize=False, margins=False)

Параметры

ПараметрЧто делаетПо умолчанию
valuesстолбец (или список) с числами для итоговвсе числовые
index / columnsчто станет строками / столбцами: столбец или списокNone
aggfuncфункция или список: "sum", "mean", "count", своя функция"mean"
fill_valueчем заполнить отсутствующие сочетанияNone
marginsдобавить итоги по строкам и столбцамFalse
normalizeв crosstab: True / "all", "index", "columns" — доли вместо количествFalse

Примеры

Данные для примеровиспользуются во всех примерах ниже
sales = pd.DataFrame({
    "city":  ["Омск", "Омск", "Тула", "Тула", "Омск", "Пермь", "Тула"],
    "drink": ["латте", "чай", "латте", "латте", "латте", "чай", "чай"],
    "month": ["янв", "янв", "янв", "фев", "фев", "фев", "фев"],
    "cups":  [30, 12, 18, 25, 20, 16, 9],
})
Сводная таблица
sales.pivot_table(values="cups", index="city", columns="drink", aggfunc="sum")
Вывод
drink  латте   чай
city
Омск    50.0  12.0
Пермь    NaN  16.0
Тула    43.0   9.0
Нули и итоги
sales.pivot_table(values="cups", index="city", columns="drink",
                  aggfunc="sum", fill_value=0, margins=True, margins_name="Итого")
Вывод
drink  латте  чай  Итого
city
Омск      50   12     62
Пермь      0   16     16
Тула      43    9     52
Итого     93   37    130
Несколько уровней строк
sales.pivot_table(values="cups", index=["city", "month"], columns="drink", aggfunc="sum", fill_value=0)
Вывод
drink        латте  чай
city  month
Омск  фев       20    0
      янв       30   12
Пермь фев        0   16
Тула  фев       25    9
      янв       18    0
Несколько функций
sales.pivot_table(values="cups", index="city", aggfunc=["sum", "count"])
Вывод
       sum count
      cups  cups
city
Омск    62     3
Пермь   16     1
Тула    52     3
Таблица частот
pd.crosstab(sales["city"], sales["drink"])                       # сколько строк в каждой паре
Вывод
drink  латте  чай
city
Омск       2    1
Пермь      0    1
Тула       2    1
Доли по строкам
pd.crosstab(sales["city"], sales["drink"], normalize="index").round(2)   # доли по строкам
Вывод
drink  латте   чай
city
Омск    0.67  0.33
Пермь   0.00  1.00
Тула    0.67  0.33

Сводная таблица без агрегации (просто переложить значения) — pivot.

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

Среднее вместо суммы

Если не передать aggfunc, в ячейках окажутся средние. Для одного значения на сочетание это незаметно, а при нескольких — итог неверный.

pivot_table без aggfunc
sales.pivot_table(values="cups", index="city", columns="drink")  # без aggfunc — среднее!
Вывод
drink  латте   чай
city
Омск    25.0  12.0
Пермь    NaN  16.0
Тула    21.5   9.0