Как стать автором
Обновить

Groupby aggregation в pandas

Время на прочтение3 мин
Количество просмотров68K


Агрегация является одной из самых частых операций при анализе данных. Разные технологии предлагают нам кучу способов эффективно группировать и агрегировать интересующие нас поля(столбцы, признаки). В этой статье будет рассказано про реализацию агрегации в pandas.
По своей специализации я очень мало работаю с python, но часто слышу про плюсы и мощь этого языка, в особенности когда речь заходит про работу с данными. Поэтому я проведу здесь параллель операций с T-SQL и приведу некотрые примеры кода. В качестве данных я буду использовать наверное самый популярный data set — Ирисы Фишера.

Первое, что приходит в голову, это получить максимальное, минимальное или среднее значение по какому-либо из параметров ириса и сгруппировать по видам этого растения, что на python с помощью pandas будет выглядить примерно следующим образом:

import pandas as pd

df = pd.read_csv('iris.csv', delimiter = ',')
print(df.groupby('variety').max()[['sepalLength']].to_markdown())

Результат:

| variety | sepal.length |
|:-----------|---------------:|
| Setosa | 5.8 |
| Versicolor | 7 |
| Virginica | 7.9 |

Либо так:

import pandas as pd
df = pd.read_csv('iris.csv', delimiter = ',')

print(df.groupby('variety').sepalLength.agg(
    maxSepalLength  = 'max',
    minSepalLength  = 'min',
    ).to_markdown())

Результат:

| variety | maxSepalLength | minSepalLength |
|:-----------|-----------------:|-----------------:|
| Setosa | 5.8 | 4.3 |
| Versicolor | 7 | 4.9 |
| Virginica | 7.9 | 4.9 |

Или с помощью лямбда выражений:

import pandas as pd
df = pd.read_csv('iris.csv', delimiter = ',')

print(df.groupby('variety').sepalLength.agg([
    lambda x: x.max(), 
    lambda x: x.min()
    ]).to_markdown())

Результат:

| variety | <lambda_0> | <lambda_1> |
|:-----------|-------------:|-------------:|
| Setosa | 5.8 | 4.3 |
| Versicolor | 7 | 4.9 |
| Virginica | 7.9 | 4.9 |

Функция экземпляра DataFrame
to_markdown()
позволяет вывести в привычном(консольном) виде таблицу(DataFrame).

На T-SQL такая операция выглядит приблизительно так:

select i.Variety, max(i.SepalLength) as maxSepalLength
    from Iris i
        group by i.Variety

Результат:

Setosa 5.8
Versicolor 7.0
Virginica 7.9

Но допустим, теперь мы хотим получить и максимальное и минимальное (если угодно среднее) значения по всем параметрам ириса, естественно для каждого вида растения, здесь саначала код на T-SQL:

select
	i.Variety 
	,max(i.SepalLength) as maxSepalLength 
	,min(i.SepalLength) as minSepalLength
	,max(i.SepalWidth) as maxSepalWidth
	,min(i.SepalWidth) as minSepalWidth
	,max(i.PetalLength) as maxPetalLength
	,min(i.PetalLength) as mibPetalLength
	,max(i.PetalWidth) as maxPetalWidth
	,min(i.PetalWidth) as minPetalWidth
from Iris i
	group by i.Variety

Результат:

Setosa 5.8 4.3 4.4 2.3 1.9 1.0 0.6 0.1
Versicolor 7.0 4.9 3.4 2.0 5.1 3.0 1.8 1.0
Virginica 7.9 4.9 3.8 2.2 6.9 4.5 2.5 1.4

В pandas возможность групповой агрегации появилась только в версии 0.25.0 от 18 июля 2019(что было делать раньше?) и тут есть несколько вариации, рассмотрим их:

import pandas as pd
df = pd.read_csv('iris.csv', delimiter = ',')

df.groupby('variety').agg(
    maxSepalLength = pd.NamedAgg(column = 'sepalLength', aggfunc = 'max'),
    minSepalLength = pd.NamedAgg(column = 'sepalLength', aggfunc = 'min'),
    maxSepalWidth = pd.NamedAgg(column = 'sepalWidth', aggfunc = 'max'),
    minSepalWidth = pd.NamedAgg(column = 'sepalWidth', aggfunc = 'min'),
    maxPetalLength = pd.NamedAgg(column = 'petalLength', aggfunc = 'max'),
    minPetalLength = pd.NamedAgg(column = 'petalLength', aggfunc = 'min'),
    maxPetalWidth = pd.NamedAgg(column = 'petalWidth', aggfunc = 'max'),
    minPetalWidth = pd.NamedAgg(column = 'petalWidth', aggfunc = 'min'),
    )

Результат:

Setosa 5.8 4.3 4.4 2.3 1.9 1.0 0.6 0.1
Versicolor 7.0 4.9 3.4 2.0 5.1 3.0 1.8 1.0
Virginica 7.9 4.9 3.8 2.2 6.9 4.5 2.5 1.4

Функция
DataFrame.agg(self, func, axis=0, *args, **kwargs)

позволяет проводить агрегацию из нескольких операций над заданной осью. В качестве параметров функция получает **kwargs(именнованные аргументы, подробнее можно посмотреть в статье на habr), которые представляют собой столбец, над которым производится операция и собтсвенно имя функции агрегирования в одинарных кавычках. Запись выглядит довольно пространно. Идем дальше.

То же решение с применением лямбда выражений выглядит гораздо более лаконично и просто:

import pandas as pd
df = pd.read_csv('iris.csv', delimiter = ',')

df.groupby('variety').agg([
    lambda x: x.max(),
    lambda x: x.min()
    ])

Результат:

Setosa 5.8 4.3 4.4 2.3 1.9 1.0 0.6 0.1
Versicolor 7.0 4.9 3.4 2.0 5.1 3.0 1.8 1.0
Virginica 7.9 4.9 3.8 2.2 6.9 4.5 2.5 1.4

Мне часто доводится слышать о гораздо меньшем количестве написанного когда Python при решении однотипных задача в сравнении с другими языками. Здесь, в сравнении с T-SQL, с этим можно согласится, однако понятность и последовательность выражений лингвистических средств таких как SQL или T-SQL напрочь теряется(личное мнение).

Data set и код из статьи можной найти здесь

What’s new in 0.25.0 (July 18, 2019)

pandas
Теги:
Хабы:
Всего голосов 3: ↑3 и ↓0+3
Комментарии0

Публикации

Истории

Работа

Python разработчик
201 вакансия
Data Scientist
98 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн