← Назад к вопросам

Группировка данных с 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. Группировки по категории и суммирования продаж
  2. Нахождения категории с максимальными продажами
  3. Добавления столбца с процентом от общих продаж

Комментарии (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 значения при группировке?
Группировка данных с pandas | PrepBro