Как работает метод `transform` в сочетании с `groupby` в Pandas?

Ответ

Метод transform после группировки (groupby) применяет заданную функцию к каждой группе отдельно и возвращает объект (Series или DataFrame) того же размера и с тем же индексом, что и исходные данные. Это ключевое отличие от agg или apply, которые возвращают сводную статистику по группам.

Основное назначение: Создание новых столбцов на основе групповых агрегатов (например, центрирование данных внутри группы, расчет ранга или доли).

Пример: Добавление среднего по группе к каждому наблюдению

import pandas as pd

df = pd.DataFrame({
    'Department': ['Sales', 'Sales', 'IT', 'IT', 'HR'],
    'Employee': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'Salary': [70000, 80000, 90000, 95000, 60000]
})

# Вычисляем среднюю зарплату по департаменту и добавляем как новый столбец
df['Dept_Avg_Salary'] = df.groupby('Department')['Salary'].transform('mean')

# Вычисляем отклонение зарплаты сотрудника от средней по его департаменту
df['Salary_Diff_From_Avg'] = df['Salary'] - df['Dept_Avg_Salary']

print(df)
Результат: Department Employee Salary Dept_Avg_Salary Salary_Diff_From_Avg
0 Sales Alice 70000 75000.0 -5000.0
1 Sales Bob 80000 75000.0 5000.0
2 IT Charlie 90000 92500.0 -2500.0
3 IT David 95000 92500.0 2500.0
4 HR Eve 60000 60000.0 0.0

Ключевые особенности transform:

  • Сохранение формы: Исходный DataFrame не "схлопывается" по группам.
  • Автоматическое выравнивание (alignment): Результат автоматически сопоставляется по индексу, что исключает ошибки слияния (merge).
  • Гибкость: Работает как со встроенными агрегаторами ('mean', 'sum', 'std'), так и с пользовательскими функциями.
  • Производительность: Часто оптимизирован и работает быстрее, чем apply в подобных сценариях.

Ответ 18+ 🔞

А, ну вот, опять этот transform после groupby! Слушай, это вообще одна из самых хитрожопых, но офигенно полезных фишек в pandas. Если в двух словах — он применяет твою функцию к каждой группе отдельно, но на выходе возвращает тебе штуку того же размера и с тем же индексом, что и было изначально. Не как agg или apply, которые схлопывают всё в сводную табличку по группам.

Зачем это, блядь, нужно? Ну, например, чтобы посчитать какую-то хрень внутри группы (типа среднего или суммы) и потом эту хрень прилепить как новый столбец к каждому исходному ряду. Центрирование данных, ранги, доли — вот это всё.

Смотри, как это работает на живом примере. Представь, что у нас отделы и зарплаты:

import pandas as pd

df = pd.DataFrame({
    'Department': ['Sales', 'Sales', 'IT', 'IT', 'HR'],
    'Employee': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
    'Salary': [70000, 80000, 90000, 95000, 60000]
})

Допустим, тебе надо для каждого сотрудника узнать, насколько он отклонился от средней зарплаты по своему отделу. Без transform пришлось бы городить огород с мерджем, а тут — раз, и готово.

# Считаем среднюю зарплату по департаменту и сразу лепим её как новый столбец
df['Dept_Avg_Salary'] = df.groupby('Department')['Salary'].transform('mean')

# Ну а теперь просто от своей зарплаты эту среднюю отнимаем — и вуаля, отклонение
df['Salary_Diff_From_Avg'] = df['Salary'] - df['Dept_Avg_Salary']

print(df)

И что мы получаем? Вот эту красоту:

Department Employee Salary Dept_Avg_Salary Salary_Diff_From_Avg
0 Sales Alice 70000 75000.0 -5000.0
1 Sales Bob 80000 75000.0 5000.0
2 IT Charlie 90000 92500.0 -2500.0
3 IT David 95000 92500.0 2500.0
4 HR Eve 60000 60000.0 0.0

Видишь? Алиса и Боб получили одно и то же среднее по отделу Sales (75к), Чарли и Дэвид — по IT (92.5к). Форма таблицы не изменилась — просто добавились столбцы. Ёперный театр, удобно же!

Так в чём же, блядь, соль transform?

  • Форма на месте: Исходная таблица не схлопнулась в три строчки по отделам. Всё осталось как есть, только обогатилось.
  • Автовыравнивание (alignment): Результат сам приклеивается по правильному индексу. Не надо вручную мерджить и потом охуевать, почему строки перепутались. Доверия к этому механизму — ебать ноль, но он работает!
  • Гибкость: Кидай туда встроенные агрегаторы ('mean', 'sum', 'std'), или свои кастомные функции — съест.
  • Скорость: Часто он быстрее, чем если бы ты через apply такое же выкручивал. Хуй с горы, но факт.

В общем, если нужно посчитать что-то внутри группы и размазать это по всем строкам — это твой инструмент. Просто помни: он возвращает столько же строк, сколько было на входе. Всё остальное — от лукавого.