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

agg и именованная агрегация

Несколько итогов по группам за один вызов — с понятными именами столбцов результата.

Нужно знать:Группировка: groupby

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

Коротко

  • agg(["sum", "mean"]) — несколько функций для выбранного столбца.
  • agg({"col": "sum", "other": ["mean", "max"]}) — свои функции для каждого столбца; столбцы результата становятся MultiIndex.
  • Именованная агрегация agg(имя=("столбец", "функция")) сразу даёт плоские и понятные имена — самый удобный вариант.
  • Функция может быть строкой ("sum", "nunique", "first") или своей функцией от Series. Строки работают быстрее.
  • as_index=False — ключи группировки обычными столбцами.

Синтаксис

df.groupby(key)["col"].agg(["sum", "mean"])
df.groupby(key).agg({"a": "sum", "b": ["min", "max"]})
df.groupby(key).agg(new_name=("col", "func"), other=("col2", my_func))
Функция Что считает
"sum", "mean", "median" сумма, среднее, медиана (без NaN)
"min", "max", "std" минимум, максимум, выборочное отклонение
"count" / "size" непустые значения / все строки
"nunique" число различных значений
"first", "last" первое / последнее непустое значение

Примеры

Данные для примеровиспользуются во всех примерах ниже
sales = pd.DataFrame({
    "city":   ["Омск", "Тула", "Омск", "Пермь", "Тула", "Омск"],
    "drink":  ["латте", "капучино", "капучино", "латте", "латте", "латте"],
    "cups":   [30, 12, 18, 25, 20, 12],
    "rating": [4.5, 4.0, None, 4.8, 3.9, 4.2],
})
Несколько функций для столбца
sales.groupby("city")["cups"].agg(["sum", "mean", "count"])
Вывод
       sum  mean  count
city
Омск    60  20.0      3
Пермь   25  25.0      1
Тула    32  16.0      2
Свои функции для каждого столбца
sales.groupby("city").agg({"cups": "sum", "rating": ["mean", "max"]})   # столбцы — MultiIndex
Вывод
      cups rating
       sum   mean  max
city
Омск    60   4.35  4.5
Пермь   25   4.80  4.8
Тула    32   3.95  4.0
Именованная агрегация
sales.groupby("city").agg(
    total_cups=("cups", "sum"),
    avg_rating=("rating", "mean"),
    drinks=("drink", "nunique"),
)
Вывод
       total_cups  avg_rating  drinks
city
Омск           60        4.35       2
Пермь          25        4.80       1
Тула           32        3.95       2
Свои функции
sales.groupby("city").agg(
    spread=("cups", lambda s: s.max() - s.min()),
    top_drink=("drink", lambda s: s.value_counts().index[0]),
)
Вывод
       spread top_drink
city
Омск       18     латте
Пермь       0     латте
Тула        8  капучино
Ключи обычными столбцами
sales.groupby("city", as_index=False).agg(total=("cups", "sum"))
Вывод
    city  total
0   Омск     60
1  Пермь     25
2   Тула     32
first, last, size
sales.groupby("city")["drink"].agg(["first", "last", "size"])
Вывод
          first   last  size
city
Омск      латте  латте     3
Пермь     латте  латте     1
Тула   капучино  латте     2

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

MultiIndex в столбцах после словаря

Словарь со списками даёт двухуровневые имена столбцов. Либо используйте именованную агрегацию, либо склейте уровни.

Плоские имена столбцов
res = sales.groupby("city").agg({"cups": ["sum", "max"]})
res.columns = ["_".join(col) for col in res.columns]     # ("cups", "sum") → "cups_sum"
res
Вывод
       cups_sum  cups_max
city
Омск         60        30
Пермь        25        25
Тула         32        20

Столбец с именем <lambda>

Безымянная функция в списке даёт столбец <lambda>. Используйте именованную агрегацию или обычную функцию с понятным именем.

lambda в списке функций
sales.groupby("city")["cups"].agg([lambda s: s.max() - s.min()])   # столбец назван <lambda>
Вывод
       <lambda>
city
Омск         18
Пермь         0
Тула          8