Pandas GroupBy: группировка, суммирование и агрегация данных в Python
Метод groupby в Pandas — это невероятно мощный инструмент, который помогает получить эффективное и значимое понимание вашего набора данных. Всего в нескольких простых строках кода вы можете агрегировать данные в чрезвычайно понятные и мощные формы.
В конце этого руководства вы научитесь работать с методом .groupby()
из библиотеки Pandas, используя разбиение-применение-сочетание. Этот процесс эффективно обрабатывает большие наборы данных для манипуляции данными очень мощными способами. Вы научитесь полностью освоить метод, включая доступ к группам, преобразование данных и создание производных данных.
Оглавление
Что такое метод GroupBy в Pandas?
Метод Pandas .groupby()
работает аналогично оператору SQL GROUP BY
. На самом деле, он разработан чтобы быть похожим на свой аналог в SQL, используя его эффективность и интуитивность. Подобно оператору GROUP BY
в SQL, метод Pandas работает путем разделения данных, их агрегирования заданным образом (или способами) и повторной комбинации данных осмысленным образом.
Поскольку метод .groupby()
сначала разделяет данные, мы можем работать с группами напрямую. Так как агрегация выполняется после разделения, у нас есть полная свобода в том, как агрегировать данные. Pandas затем объединяет данные, чтобы представить их в виде осмысленного DataFrame.
Что замечательно в этом, так это то, что он позволяет нам использовать метод по-разному, особенно творчески. Благодаря этому метод является основой для понимания, как Pandas можно использовать для манипуляции и анализа данных. Длина этого руководства отражает его сложность и важность!
Почему Pandas предлагает несколько способов агрегации данных?
Pandas предоставляет множество вариантов для анализа и агрегации данных. Почему существует, казалось бы, так много пересекающихся методов? Ответ заключается в том, что каждый метод, такой как .pivot()
, .pivot_table()
, .groupby()
, предлагает уникальный подход к агрегации данных. Они не просто являются переименованными версиями, а представляют собой полезные способы для выполнения различных задач.
Загрузка образца Pandas DataFrame
Чтобы следовать этому руководству, давайте загрузим пример DataFrame из библиотеки Pandas. Загрузим воображаемые данные о продажах, используя набор данных, размещенный на странице datagy на Github. Если вы хотите следовать инструкции шаг за шагом, скопируйте приведенный ниже код для загрузки набора данных с помощью метода .read_csv()
# Загрузка образцового DataFrame из файла CSV с датами в столбце 'date'
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/datagy/data/main/sales.csv', parse_dates=['date'])
print(df.head())
# Вывод:
# date gender region sales
# 0 2022-08-22 Male North-West 20381
# 1 2022-03-05 Male North-East 14495
# 2 2022-02-09 Male North-East 13510
# 3 2022-06-22 Male North-East 15983
# 4 2022-08-10 Female North-West 15007
Вывод первых пяти строк с помощью метода .head()
дает некоторое представление о наших данных. Видно, что у нас есть столбец date
, содержащий дату транзакции. У нас есть строковые столбцы, охватывающие gender
и region
нашего продавца. Наконец, у нас есть целочисленный столбец sales
, представляющий общую стоимость продаж.
Понимание группирования объектов Pandas
Давайте впервые взглянем на метод Pandas .groupby()
. Мы можем создать объект GroupBy
, применив метод к нашему DataFrame и передав либо столбец, либо список столбцов. Посмотрим, как это выглядит: создадим объект GroupBy и выведем его на экран.
# Создание объекта группировки DataFrame Pandas по столбцу 'region'
print(df.groupby('region'))
# Вывод:
# <pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fb78815a4f0>
Мы видим, что это вернуло объект типа DataFrameGroupBy. Поскольку это объект, мы можем изучить некоторые его атрибуты.
Pandas GroupBy Attributes
Например, эти объекты имеют атрибут .ngroups
, который содержит количество групп, доступных в этом групп
# Подсчет количества групп в объекте группировки DataFrame Pandas по столбцу 'region'
print(df.groupby('region').ngroups)
# Вывод:
# 3
Мы можем увидеть, что наш объект имеет 3 группы. Аналогично, мы можем использовать атрибут .groups
, чтобы получить представление о специфике получившихся групп. Вывод этого атрибута — это объект, похожий на словарь, который содержит наши группы в качестве ключей. Значения этих ключей — это индексы строк, принадлежащих этой группе!
# Доступ к группам в объекте группировки DataFrame Pandas по столбцу 'region'
print(df.groupby('region').groups)
# Вывод:
# {'North-East': [1, 2, 3, ...], 'North-West': [0, 4, 7, ...], 'South': [5, 6, 8, ...]}
Если мы хотим увидеть только названия групп нашего объекта GroupBy, мы можем просто вернуть только ключи этого словаря.
# Доступ только к именам групп в объекте группировки DataFrame PandAs по столбцу 'region'
print(df.groupby('region').groups.keys())
# Вывод:
# dict_keys(['North-East', 'North-West', 'South'])
Мы можем видеть, насколько полезен этот метод! Он позволяет нам группировать данные значимым образом.
Выбор группы PandasПо группе
Мы также можем выбрать все записи, принадлежащие определенной группе. Это может быть полезно, если вы хотите увидеть данные каждой группы. Чтобы сделать это, мы можем применить метод .get_group()
и передать имя группы, которую мы хотим выбрать. Давайте попробуем выбрать регион 'South'
из нашего объекта GroupBy:
# Выбор группы из объекта группировки DataFrame Pandas по столбцу 'region'
print(df.groupby('region').get_group('South'))
# Вывод:
# date gender region sales
# 5 2022-09-06 Male South 21792
# 6 2022-08-21 Male South 20113
# 8 2022-11-22 Male South 14594
# 9 2022-01-16 Female South 24114
# 10 2022-12-21 Male South 35154
# .. ... ... ... ...
# 972 2022-06-09 Male South 22254
# 979 2022-11-24 Female South 25591
# 981 2022-12-05 Male South 34334
# 985 2022-12-01 Female South 21282
# 994 2022-09-29 Male South 21255
# [331 rows x 4 columns]
Это может быть весьма полезно, если вы хотите получить некоторое представление о данных. Аналогично, это дает вам понимание того, как метод .groupby()
на самом деле используется для агрегирования данных. В следующем разделе вы узнаете, как работает метод Pandas groupby, используя методологию разделения, применения и объединения.
Понимание Pandas GroupBy Разделение-Применение-Объединение
Метод groupby в Pandas использует процесс, известный как "разделяй, применяй и объединяй", для полезной агрегации или модификации DataFrame. Этот процесс работает точно так, как и назван.
Разделение данных на группы в зависимости от определенных критериев
Применение функции к каждой группе независимо
Объединение результатов в подходящую структуру данных
В предыдущем разделе, когда вы применили метод .groupby()
и передали в него столбец, вы уже выполнили первый шаг! Вы смогли разделить данные на соответствующие группы, основываясь на переданных вами критериях.
Причина применения этого метода заключается в том, чтобы разбить проблему анализа больших данных на управляемые части. Это позволяет выполнять операции над отдельными частями и затем объединять их. Хотя шаги применения и объединения выполняются по отдельности, Pandas абстрагирует их, создавая впечатление единого шага.
Использование Split-Apply-Combine без GroupBy
Прежде чем углубляться в то, как работает метод .groupby()
, давайте посмотрим, как мы можем воспроизвести его без использования этой функции. Преимущество этого подхода заключается в том, что мы можем легко понять каждый шаг процесса.
Разделение данных: Начнем с разделения данных – мы можем пройтись по каждому уникальному значению в DataFrame, разделяя данные по столбцу
'region'.
Применение функции агрегации: Оттуда мы можем выбрать строки из DataFrame, соответствующие условию, и применить к ним функцию.
# Репликация процесса split-apply-combine без использования GroupBy
# Создание контейнерного словаря для хранения средних значений по каждой группе
averages = {}
# Разделение данных на различные регионы
for region in df['region'].unique():
tempdf = df[df['region'] == region]
# Применение функции агрегации для вычисления среднего значения продаж
average = tempdf['sales'].mean()
# Сборка данных в DataFrame
averages[region] = [average]
# Создание DataFrame из словаря с средними значениями по каждому региону
aggregate_df = pd.DataFrame.from_dict(averages, orient='index', columns=['Average Sales'])
print(aggregate_df)
# Вывод:
# Average Sales
# North-West 15257.732919
# North-East 17386.072046
# South 24466.864048
Это много кода, чтобы написать для простой агрегации! К счастью, метод groupby в Pandas делает это намного проще. В следующем разделе вы узнаете, как значительно упростить этот процесс.
Агрегирование данных с помощью Pandas GroupBy
В этом разделе вы узнаете, как использовать метод groupby из Pandas для агрегации данных различными способами. Мы попробуем воссоздать тот же результат, о котором вы узнали ранее, чтобы увидеть, насколько проще на самом деле этот процесс! Давайте посмотрим, как выглядит код, а затем разберем, как он работает:
# Агрегация данных с использованием метода .groupby() из библиотеки Pandas
averages = df.groupby('region')['sales'].mean()
print(averages)
# Вывод:
# region
# North-East 17386.072046
# North-West 15257.732919
# South 24466.864048
# Name: sales, dtype: float64
Посмотрите на код! Мы смогли сократить шесть строк кода до одной! Давайте разберем это по элементам:
df.groupby('region')
вам уже знакомо. Оно разделяет данные на различные группы на основе столбцаregion
.['sales']
выбирает только этот столбец из групп.mean()
применяет метод вычисления среднего для каждого столбца в группе.Данные объединены в результирующий DataFrame,
averages
Давайте более наглядно рассмотрим весь процесс. Чтобы упростить понимание, давайте посмотрим только на первые семь записей DataFrame:

.groupby()
На изображении выше вы можете увидеть, как данные сначала разделяются на группы, выбирается столбец, затем применяется агрегирование, и полученные данные объединяются.
Другие агрегации с Pandas GroupBy
Теперь, когда вы понимаете, как работает процедура разделения, применения и объединения, давайте рассмотрим некоторые другие способы агрегации в Pandas. Таблица ниже предоставляет обзор доступных функций агрегации:
.count()
Количество ненулевых записей
.sum()
Сумма значения
.mean()
Среднее арифметическое значений
.median()
Медиана значений
.min()
Минимальное значение группы
.max()
Максимальное значение группы
.mode()
Наиболее часто встречающееся значение в группе
.std()
Стандартное отклонение группы
.var()
Дисперсия группы
Например, если мы захотим вычислить стандартное отклонение для каждой группы, мы могли бы просто написать:
# Вычисление стандартного отклонения продаж для каждой группы по региону
standard_deviations = df.groupby('region')['sales'].std()
print(standard_deviations)
# Вывод:
# region
# North-East 2032.541552
# North-West 3621.456493
# South 5253.702513
# Name: sales, dtype: float64
Применение множественных агрегаций с использованием Pandas GroupBy
Pandas также предоставляет дополнительный метод .agg()
, который позволяет применять несколько агрегирующих функций в методе .groupby()
. Этот метод позволяет передавать список вызовов (т. е. функции без скобок). Давайте посмотрим, как мы можем использовать некоторые функции из библиотеки numpy
для агрегации.
# Применение нескольких агрегатных функций с использованием метода .agg()
import numpy as np
aggs = df.groupby('region')['sales'].agg([np.mean, np.std, np.var])
print(aggs)
# Вывод:
# mean std var
# region
# North-East 17386.072046 2032.541552 4.131225e+06
# North-West 15257.732919 3621.456493 1.311495e+07
# South 24466.864048 5253.702513 2.760139e+07
Метод .agg()
позволяет легко генерировать сводные статистические данные по различным группам. Без этого нам пришлось бы применять метод .groupby()
три раза, но здесь мы смогли сократить это до одного вызова метода!
Преобразование данных с помощью Pandas GroupBy
Еще один невероятно полезный способ использовать метод groupby в Pandas — это трансформация данных. Что это значит? Трансформируя данные, вы выполняете операцию, специфичную для этой группы. Это может включать, например, стандартизацию данных только на основе этой группы с использованием z-оценки или заполнение отсутствующих данных, вводя значение на основе этой группы.
Операция трансформации отличается от агрегации и фильтрации с использованием .groupby()
, тем что результирующий DataFrame имеет такие же размеры, как и исходные данные. Хотя это может быть верно для агрегации и фильтрации, для трансформации это всегда верно.
Метод .transform()
вернет одно значение для каждой записи в оригинальном наборе данных. Поэтому, гарантируется, что размер результата будет совпадать.
Использование .transform в GroupBy
Давайте рассмотрим пример преобразования данных в Pandas DataFrame. В этом примере мы рассчитаем, какой процент от общих продаж региона составляет каждая продажа. Для этого мы можем применить метод .transform()
к объекту GroupBy. Мы можем передать функцию 'sum'
, чтобы вернуть сумму для всей группы в каждой строке. Наконец, мы делим исходный столбец 'sales'
на эту сумму.
Давайте посмотрим, как выглядит этот код:
# Вычисление процента продаж региона
df['Percent Of Region Sales'] = df['sales'] / df.groupby('region')['sales'].transform('sum')
print(df.head())
# Вывод:
# date gender region sales Percent Of Region Sales
# 0 2022-08-22 Male North-West 20381 0.004148
# 1 2022-03-05 Male North-East 14495 0.002403
# 2 2022-02-09 Male North-East 13510 0.002239
# 3 2022-06-22 Male North-East 15983 0.002649
# 4 2022-08-10 Female North-West 15007 0.003055
В полученной таблице видно, какую часть от общего объема продаж в регионе составила каждая продажа.
Преобразование данных без .transform
В предыдущем разделе вы преобразовали данные с помощью функции .transform()
, но мы также можем применить функцию, которая вернет одно значение без агрегации. Например, давайте применим метод .rank()
к нашей группировке. Это позволит нам ранжировать значения в каждой группе. Вместо использования метода .transform()
, мы непосредственно применим метод .rank()
# Преобразование DataFrame с использованием GroupBy
df['ranked'] = df.groupby('region')['sales'].rank(ascending=False)
print(df.sort_values(by='sales', ascending=False).head())
# Вывод:
# date gender region sales ranked
# 61 2022-02-22 Female South 43775 1.0
# 673 2022-04-19 Male South 37878 2.0
# 111 2022-10-31 Female South 36444 3.0
# 892 2022-09-05 Male South 35723 4.0
# 136 2022-02-27 Male South 35485 5.0
В этом случае метод .groupby()
возвращает серию Pandas такой же длины, как и исходный DataFrame. Поэтому мы можем просто присвоить эту серию новому столбцу.
Фильтрация данных с помощью Pandas GroupBy
Замечательный способ использования метода .groupby()
— фильтрация DataFrame. Этот подход значительно отличается от обычной фильтрации, так как позволяет применять метод фильтрации на основе некоторых агрегаций значений группы. Например, мы можем отфильтровать наш DataFrame, чтобы удалить строки, где средняя цена продажи группы меньше 20,000.
# Фильтрация строк, где средняя цена продаж в группе меньше 20,000
df = df.groupby('region').filter(lambda x: x['sales'].mean() < 20000)
print(df.head())
# Вывод:
# date gender region sales
# 0 2022-08-22 Male North-West 20381
# 1 2022-03-05 Male North-East 14495
# 2 2022-02-09 Male North-East 13510
# 3 2022-06-22 Male North-East 15983
# 4 2022-08-10 Female North-West 15007
Let’s break down how this works:
We group our data by the
'region'
columnWe apply the
.filter()
method to filter based on a lambda function that we pass inThe lambda function evaluates whether the average value found in the group for the
'sales'
column is less than 20,000
Этот подход избавляет нас от необходимости сначала определять среднее значение для каждой группы, а затем отфильтровывать эти значения. В данном примере подход может показаться немного излишним. Однако он открывает огромный потенциал при работе с более мелкими группами.
Группировка Pandas DataFrame по нескольким столбцам
Мы можем расширить функциональность метода Pandas .groupby()
, группируя данные по нескольким столбцам. Ранее вы группировали DataFrame только по одному столбцу, передавая строку, представляющую столбец. Однако можно также передать список строк, представляющих различные столбцы. Это позволяет разделить данные еще более детально.
Давайте вычислим сумму всех продаж, разделенных по 'region'
и по 'gender'
, написав.
# Агрегация данных по нескольким столбцам
sums = df.groupby(['region', 'gender'])['sales'].sum()
print(sums.head())
# Вывод:
# sales
# region gender
# North-East Female 3051132
# Male 2981835
# North-West Female 2455899
# Male 2457091
# South Female 4135688
Более того, все методы, которые мы рассмотрели ранее, также возможны и в этом случае. Например, мы могли бы применить функцию .rank()
снова и определить топ-продажи в каждой комбинации регион
# Ранжирование продаж по регионам и полам
df['rank'] = df.groupby(['region', 'gender'])['sales'].rank(ascending=False)
print(df.head())
# Вывод:
# date gender region sales rank
# 0 2022-08-22 Male North-West 20381 11.0
# 1 2022-03-05 Male North-East 14495 154.0
# 2 2022-02-09 Male North-East 13510 168.0
# 3 2022-06-22 Male North-East 15983 138.0
# 4 2022-08-10 Female North-West 15007 89.5
Использование пользовательских функций с Pandas GroupBy
Еще одна отличная функция метода .groupby()
в Pandas заключается в том, что мы можем применять наши собственные функции. Это позволяет определять функции, которые соответствуют потребностям нашего анализа. Вы уже видели это в примере фильтрации с использованием метода .groupby()
. Мы можем использовать либо анонимную лямбда-функцию, либо сначала определить функцию и применить ее.
Давайте посмотрим, как это может работать. Мы можем определить пользовательскую функцию, которая будет возвращать диапазон группы, вычисляя разницу между минимальным и максимальным значениями. Давайте определим эту функцию и применим её к нашему вызову метода .groupby()
.
# Использование пользовательской функции в объекте GroupBy
def group_range(x):
return x.max() - x.min()
ranges = df.groupby(['region', 'gender'])['sales'].apply(group_range)
print(ranges)
# Вывод:
# region gender
# North-East Female 10881
# Male 10352
# North-West Female 20410
# Male 17469
# South Female 30835
# Male 27110
# Name: sales, dtype: int64
Функция group_range()
принимает один параметр, который в данном случае представляет собой серии наших группировок 'sales'
. Мы находим наибольшее и наименьшее значения и возвращаем разницу между ними. Это может быть полезно для оценки различий в диапазонах разных групп.
Полезные примеры Pandas GroupBy
В этом разделе вы узнаете о полезных вариантах использования метода Pandas .groupby()
. Примеры в этом разделе призваны продемонстрировать более креативные способы использования метода. Эти примеры предназначены для вдохновения и расширения вашего понимания различных способов использования метода.
Получение первых n строк группы PandasАвтор
Давайте посмотрим, как вы можете вернуть пять строк из каждой группы в результирующий DataFrame. Это может быть особенно полезно, когда вы хотите получить представление о том, как могут выглядеть данные в каждой группе. Если порядок сортировки данных в DataFrame не имеет значения, вы можете просто использовать функцию .head()
, чтобы вернуть любое количество записей из каждой группы.
Давайте рассмотрим, как вернуть две записи из каждой группы, где каждая группа определяется регионом и полом:
# Возврат первых двух записей из каждого группы
print(df.groupby(['region', 'gender']).head(2))
# Вывод:
# date gender region sales
# 0 2022-08-22 Male North-West 20381
# 1 2022-03-05 Male North-East 14495
# 4 2022-08-10 Female North-West 15007
# 5 2022-09-06 Male South 21792
# 7 2022-07-08 Male North-West 13650
# 9 2022-01-16 Female South 24114
# 11 2022-04-30 Female North-West 19631
# 12 2022-11-25 Female North-East 18262
# 13 2022-08-14 Female North-East 13733
# 20 2022-01-21 Female South 32313
Получение n-го самого большого ряда группы PandasАвтор
В этом примере вы узнаете, как выбрать n-е по величине значение в заданной группе. Для этого мы можем использовать метод .nlargest()
, который вернет n-е по величине значение. Например, если мы хотим вернуть второе по величине значение в каждой группе, мы можем просто передать значение 2. Давайте посмотрим, как это выглядит:
# Получение второй по величине значения в каждой группе
print(df.groupby(['region', 'gender'])['sales'].nlargest(2))
# Вывод:
# region gender
# North-East Female 407 22545.0
# Male 560 22361.0
# 442 21951.0
# North-West Female 758 26813.0
# Male 844 23553.0
# 576 23485.0
# South Female 61 43775.0
# Male 673 37878.0
# 892 35723.0
# Name: sales, dtype: float64
Упражнения
Пора проверить свои знания! Используйте упражнения ниже, чтобы попрактиковаться в использовании метода .groupby()
. Решения можно найти, нажав на раздел под каждым вопросом.
Заключение и резюме
В этом уроке вы узнали о методе .groupby()
в Pandas. Этот метод позволяет анализировать, агрегировать, фильтровать и преобразовывать ваши данные множеством полезных способов. Ниже вы найдёте краткое резюме метода .groupby()
в Pandas:
Метод
.groupby()
в Pandas позволяет выполнять агрегирование, преобразование и фильтрацию DataFrameМетод работает с использованием операций разделения, преобразования и применения
Вы можете сгруппировать данные по нескольким столбцам, передав список столбцов
Вы можете легко применять несколько агрегатов, используя метод
.agg()
Вы можете использовать метод для преобразования ваших данных полезными способами, такими как вычисление z-оценок или ранжирование данных по различным группам.
Официальную документацию для метода Pandas .groupby()
можно найти здесь
Дополнительные ресурсы
To learn more about related topics, check out the tutorials below:
Pandas: подсчет уникальных значений в объекте GroupBy
Python Defaultdict: обзор и примеры
Вычислить средневзвешенное значение в Pandas и Python
Last updated