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

Groupby aggregation в pandas

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


Агрегация является одной из самых частых операций при анализе данных. Разные технологии предлагают нам кучу способов эффективно группировать и агрегировать интересующие нас поля(столбцы, признаки). В этой статье будет рассказано про реализацию агрегации в 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
Комментарии 0
Комментарии Комментировать

Публикации

Истории

Работа

Data Scientist
66 вакансий
Python разработчик
136 вакансий

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

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн