Операции 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)
# Создание тестовых данных
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())
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)
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"]))
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")
))
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)
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)
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 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))
# Смоделировать данные о продажах
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 — ключевая операция в анализе данных; освоив её, вы сможете эффективно выполнять различные задачи статистического анализа.