← Назад к вопросам
Группировка данных с pandas
1.2 Junior🔥 171 комментариев
#Python Core
Условие
Дан DataFrame с продажами:
import pandas as pd
df = pd.DataFrame({
"category": ["A", "B", "A", "B", "A"],
"sales": [100, 200, 150, 300, 50]
})
Напишите код для:
- Группировки по категории и суммирования продаж
- Нахождения категории с максимальными продажами
- Добавления столбца с процентом от общих продаж
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Группировка данных с pandas
GroupBy — одна из самых мощных операций в pandas, позволяющая легко агрегировать и анализировать данные. Разберём все три задачи.
1. Группировка и суммирование
import pandas as pd
df = pd.DataFrame({
"category": ["A", "B", "A", "B", "A"],
"sales": [100, 200, 150, 300, 50]
})
# Способ 1: Простая группировка
grouped_sales = df.groupby("category")["sales"].sum()
print(grouped_sales)
# category
# A 300
# B 500
# Name: sales, dtype: int64
# Способ 2: С восстановлением DataFrame
grouped_df = df.groupby("category")["sales"].sum().reset_index()
print(grouped_df)
# category sales
# 0 A 300
# 1 B 500
# Способ 3: Несколько агрегаций одновременно
agg_df = df.groupby("category")["sales"].agg([
("total", "sum"),
("count", "count"),
("mean", "mean")
]).reset_index()
print(agg_df)
# category total count mean
# 0 A 300 3 100.0
# 1 B 500 2 250.0
2. Нахождение категории с максимальными продажами
# Способ 1: idxmax() — возвращает индекс максимума
max_category = grouped_sales.idxmax()
max_value = grouped_sales.max()
print(f"Категория с макс. продажами: {max_category} ({max_value})")
# Категория с макс. продажами: B (500)
# Способ 2: Через исходный DataFrame
max_row = grouped_df.loc[grouped_df["sales"].idxmax()]
print(max_row)
# category B
# sales 500
# Name: 1, dtype: object
# Способ 3: nlargest() — найти N самых больших значений
top_3 = grouped_df.nlargest(3, "sales")
print(top_3)
# category sales
# 1 B 500
# 0 A 300
# Способ 4: Найти всю информацию о категории с макс продажами
max_sales_per_category = df.groupby("category")["sales"].sum().reset_index()
max_category_info = max_sales_per_category[max_sales_per_category["sales"] == max_sales_per_category["sales"].max()]
print(max_category_info)
# category sales
# 1 B 500
3. Добавление столбца с процентом от общих продаж
# Способ 1: Присчитываем к исходному DataFrame
df["category_total"] = df.groupby("category")["sales"].transform("sum")
df["total_sales"] = df["sales"].sum()
df["percentage"] = (df["category_total"] / df["total_sales"] * 100).round(2)
print(df)
# category sales category_total total_sales percentage
# 0 A 100 300 800 37.50
# 1 B 200 500 800 62.50
# 2 A 150 300 800 37.50
# 3 B 300 500 800 62.50
# 4 A 50 300 800 37.50
# Способ 2: Компактнее — одна строка
df["percentage"] = (df.groupby("category")["sales"].transform("sum") / df["sales"].sum() * 100).round(2)
# Способ 3: Процент от строк (не от категории)
df["pct_of_total"] = (df["sales"] / df["sales"].sum() * 100).round(2)
print(df)
# category sales pct_of_total
# 0 A 100 12.50
# 1 B 200 25.00
# 2 A 150 18.75
# 3 B 300 37.50
# 4 A 50 6.25
Полное решение одного примера
import pandas as pd
# Исходные данные
df = pd.DataFrame({
"category": ["A", "B", "A", "B", "A"],
"sales": [100, 200, 150, 300, 50]
})
print("=== Исходные данные ===")
print(df)
print("\n=== 1. Группировка и суммирование ===")
grouped = df.groupby("category")["sales"].sum().reset_index()
print(grouped)
print("\n=== 2. Категория с максимальными продажами ===")
max_idx = grouped["sales"].idxmax()
max_category = grouped.loc[max_idx]
print(f"Категория: {max_category['category']}, Продажи: {max_category['sales']}")
print("\n=== 3. Добавление процентов ===")
df["category_total"] = df.groupby("category")["sales"].transform("sum")
total = df["sales"].sum()
df["percentage"] = (df["category_total"] / total * 100).round(2)
print(df[["category", "sales", "percentage"]])
Продвинутые техники GroupBy
1. Фильтрация групп
# Оставить только группы с суммой > 300
filtered = df.groupby("category")["sales"].sum()
filtered = filtered[filtered > 300]
print(filtered)
# category
# B 500
2. Несколько колонок для группировки
df2 = pd.DataFrame({
"region": ["US", "US", "EU", "EU", "US"],
"category": ["A", "B", "A", "B", "A"],
"sales": [100, 200, 150, 300, 50]
})
# Группировка по двум колонкам
df2.groupby(["region", "category"])["sales"].sum()
# region category
# EU A 150
# B 300
# US A 150
# B 200
3. Применение функции к группе
# Пользовательская функция
def custom_agg(x):
return {
"min": x.min(),
"max": x.max(),
"range": x.max() - x.min()
}
df.groupby("category")["sales"].apply(custom_agg)
4. Transform — применить функцию и вернуть исходный размер
# transform сохраняет индексы исходного DataFrame
df["zscore"] = df.groupby("category")["sales"].transform(lambda x: (x - x.mean()) / x.std())
print(df)
5. Ранжирование внутри группы
df["rank_in_category"] = df.groupby("category")["sales"].rank(ascending=False)
print(df)
# category sales rank_in_category
# 0 A 100 2.0
# 1 B 200 2.0
# 2 A 150 1.0
# 3 B 300 1.0
# 4 A 50 3.0
Сравнение методов
| Метод | Назначение | Возвращает |
|---|---|---|
agg() | Агрегация (sum, mean, count) | Series/DataFrame размера групп |
transform() | Применить функцию, сохранить размер | Series/DataFrame исходного размера |
apply() | Произвольная функция на группу | Результат функции |
filter() | Отфильтровать группы | Исходный DataFrame (подмножество) |
Производительность: groupby vs pivot_table
# Для простых агрегаций pivot_table может быть проще и быстрее
pivot = df.pivot_table(values="sales", index="category", aggfunc="sum")
print(pivot)
# sales
# category
# A 300
# B 500
Частые ошибки
# Ошибка 1: забыли reset_index()
grouped = df.groupby("category")["sales"].sum() # Series с индексом
# Исправление: .reset_index()
# Ошибка 2: неправильный выбор колонок
df.groupby("category").sum() # Просуммирует все числовые колонки
# Исправление: df.groupby("category")["sales"].sum()
# Ошибка 3: потеря исходного порядка
grouped = df.groupby("category")["sales"].sum()
# Исправление: .reset_index().sort_values(...)
Что спросит интервьюер
- Разница между
agg()иtransform()? - Как отфильтровать группы по условию?
- Как сохранить исходный размер DataFrame?
- Производительность groupby на больших данных?
- Как обработать NaN значения при группировке?