Операции GroupBy в Pandas (groupby)

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


Основы использования groupby

Группировка по одному столбцу

Пример

import pandas as pd

# Создание тестовых данных
df = pd.DataFrame({
    "Отдел": ["Технологии", "Продажи", "Технологии", "Операции", "Продажи", "Технологии"],
    "Имя": ["Чжан Сань", "Ли Сы", "Ван У", "Чжао Лю", "Цянь Ци", "Сунь Ба"],
    "Зарплата": [12000, 15000, 11000, 18000, 14000, 13000]
})

print("Исходные данные:")
print(df)
print()

# Группировка по отделу
grouped = df.groupby("")
print(f"Сгруппировано: {type(grouped)}")
print(f"Количество групп: {len(grouped)}")
print()

# Просмотр групп
print("Данные для каждой группы:")
for name, group in grouped:
    print(f"\nОтдел: {name}")
    print(group)

Группировка и агрегирование

Пример

import pandas as pd

df = pd.DataFrame({
    "Отдел": ["Технологии", "Продажи", "Технологии", "Операции", "Продажи"],
    "Зарплата": [12000, 15000, 11000, 18000, 14000]
})

print("Средняя зарплата по отделам:")
print(df.groupby("Department")["Salary"].mean())
print()

print("Сумма по отделам:")
print(df.groupby("Department")["Salary"].sum())
print()

print("Количество по отделам:")
print(df.groupby("Department").size())

Группировка по нескольким столбцам

Пример

import pandas as pd

df = pd.DataFrame({
    "Year": ["2023", "2023", "2024", "2024"],
    "Отдел": ["Технологии", "Продажи", "Технологии", "Sales"],
    "Зарплата": [12000, 15000, 13000, 16000]
})

print("Группировка по году и отделу:")
print(df.groupby(["Year", "Department"])["Salary"].sum())
print()

# Вывод в виде DataFrame
result = df.groupby(["Year", "Department"]).agg({
    "Salary": "sum"
}).reset_index()
print("Результирующий DataFrame:")
print(result)

Общие функции агрегации

Одиночная агрегация

Функция Описание
sum() Sum
mean() Среднее
median() Медиана
std() Стандартное отклонение
min() / max() Минимум/Максимум
count() Count
first() / last() Первое/последнее значение

Пример

import pandas as pd

df = pd.DataFrame({
    "Отдел": ["Технологии", "Продажи", "Технологии", "Операции"],
    "Зарплата": [12000, 15000, 11000, 18000]
})

# Цепочка нескольких агрегаций
print("Цепочка агрегаций:")
print(df.groupby("Department")["Salary"].agg(["sum", "mean", "max", "min"]))

Пользовательская агрегация

Пример

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "Отдел": ["Технологии", "Продажи", "Технологии", "Операции"],
    "Зарплата": [12000, 15000, 11000, 18000]
})

# Пользовательская функция агрегации
def range_func(x):
    return x.max() - x.min()

print("Использование пользовательской функции:")
print(df.groupby("Department")["Salary"].agg(range_func))
print()

# Именованная агрегация (рекомендуется)
print("Именованная агрегация:")
print(df.groupby("Department").agg(
Минимальная зарплата=("Salary", "min"),
Максимальная зарплата=("Salary", "max"),
Средняя зарплата=("Salary", "mean")
))

transform

transform может вычислять для каждой группы, сохраняя исходную форму данных, и возвращать результат той же формы, что и исходные данные.

Пример

import pandas as pd

df = pd.DataFrame({
    "Отдел": ["Технологии", "Продажи", "Технологии", "Операции", "Продажи"],
    "Зарплата": [12000, 15000, 11000, 18000, 14000]
})

print("Исходные данные:")
print(df)
print()

# Вычислить среднюю зарплату для каждого отдела и распространить её на каждую строку
df["Средняя зарплата по отделу"] = df.groupby("Отдел")["Зарплата"].transform("mean")
print("После добавления средней зарплаты по отделу:")
print(df)
print()

# Вычислить зарплату каждого сотрудника как процент от зарплаты по отделу
df["Процент зарплаты"] = df["Зарплата"] / df["Средняя зарплата по отделу"]
print("Доля зарплаты:")
print(df)

filter Фильтрация

filter может фильтровать данные на основе групповых условий.

Пример

import pandas as pd

df = pd.DataFrame({
    "Отдел": ["Технологии", "Продажи", "Технологии", "Операции", "Продажи", "Технологии"],
    "Зарплата": [12000, 15000, 11000, 18000, 14000, 13000]
})

print("Исходные данные:")
print(df)
print()

# Отфильтровать отделы, у которых средняя зарплата больше 13000
print("Средняя зарплата по отделу > 13000:")
filtered = df.groupby("Отдел").filter(lambda x: x["Salary"].mean() > 13000)
print(filtered)
print()

# Отфильтровать группы с количеством больше 2
print("Количество участников > 2:")
filtered2 = df.groupby("Department").filter(lambda x: len(x) > 2)
print(filtered2)

apply Пользовательские функции

apply позволяет применять пользовательские функции к каждой группе.

Пример

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "Отдел": ["Технологии", "Продажи", "Технологии", "Операции"],
    "Зарплата": [12000, 15000, 11000, 18000]
})

# Применить пользовательскую функцию к каждой группе
result = df.groupby("Department").apply(
    lambda x: pd.Series({
        "Sum": x["Salary"].sum(),
        "Mean": x["Salary"].mean()
    })
)
print("Результат пользовательской агрегации:")
print(result)

Практическое задание: анализ данных о продажах

Пример

import pandas as pd

# Смоделировать данные о продажах
sales = pd.DataFrame({
    "Date": pd.date_range("2024-01-01", periods=30, freq="D"),
    "Product": ["Mobile", "Computer", "Tablet"] * 10,
    "Channel": ["Online"] * 15 + ["Offline"] * 15,
    "Sales amount": [1000, 2000, 1500] * 10
})

print("=== Анализ данных о продажах ==="\n")

# 1. Статистика по продуктам
print("1. Статистика по продуктам:")
product_summary = sales.groupby("Product")["Sales amount"].agg(["sum", "mean", "count"])
print(product_summary)
print()

# 2. Статистика по каналам
print("2. Статистика по каналам:")
channel_summary = sales.groupby("Channel")["Sales amount"].sum()
print(channel_summary)
print()

# 3. Перекрёстная статистика по продуктам и каналам
print("3. Перекрёстная статистика продукт × канал:")
cross_summary = sales.groupby(["Product", "Channel"])["Sales amount"].sum().unstack()
print(cross_summary)
print()

# 4. Расчёт доли продаж по каждому продукту
print("4. Доля продаж:")
total = sales["Sales amount"].sum()
product_pct = sales.groupby("Product")["Sales amount"].sum() / total * 100
print(product_pct.round(2))

groupby — ключевая операция в анализе данных; освоив её, вы сможете эффективно выполнять различные задачи статистического анализа.

Другие расширения