Agregação por grupo em pandas



A agregação é uma das operações mais comuns na análise de dados. Diferentes tecnologias nos oferecem várias maneiras de agrupar e agregar efetivamente os campos de interesse para nós (colunas, atributos). Este artigo abordará a implementação da agregação em pandas.
Na minha especialização, trabalho muito pouco com python, mas frequentemente ouço falar sobre os prós e o poder dessa linguagem, especialmente quando se trata de trabalhar com dados. Portanto, vou desenhar aqui uma operação paralela com o T-SQL e dar alguns exemplos de código. Como os dados, provavelmente utilizarei o conjunto de dados mais popular - Irises Fisher .

A primeira coisa que vem à mente é obter o valor máximo, mínimo ou médio para qualquer um dos parâmetros da íris e agrupar por espécie desta planta, que em python usando pandas será algo parecido com isto:

import pandas as pd

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

Resultado:

| variedade | sepal.length |
|: ----------- | ---------------: |
| Setosa 5,8 |
| Versicolor | 7
| Virginica 7,9 |

Ou então:

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

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

Resultado:

| variedade | maxSepalLength | minSepalLength |
|: ----------- | -----------------: | ----------------- : |
| Setosa 5,8 | 4.3
| Versicolor | 7 4.9 |
| Virginica 7,9 | 4.9 |

Ou usando expressões lambda:

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())

Resultado:

| variedade | <lambda_0> | <lambda_1> |
|: ----------- | -------------: | -------------: |
| Setosa 5,8 | 4.3
| Versicolor | 7 4.9 |
| Virginica 7,9 | 4.9 |

Função de instância DataFrame
to_markdown()
permite exibir uma tabela (DataFrame) no formato usual (console).

No T-SQL, esta operação se parece com isso:

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

Resultado:

Setosa 5.8
Versicolor 7.0
Virginica 7.9

Mas suponha que agora queremos obter os valores máximo e mínimo (se você gosta da média) para todos os parâmetros da íris, naturalmente para cada tipo de planta, o código T-SQL foi gerado aqui:

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

Resultado:

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

Nos pandas, a possibilidade de agregação de grupo apareceu apenas na versão 0.25.0 de 18 de julho de 2019 (o que foi feito antes) ?) e existem várias variações, considere-as:

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'),
    )

Resultado:

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 ​​2,0 5,1 3,0 1,8 1,0
Virginica 7,9 4,9 3,8 3,8 2,2 6,9 4,5 2,5 1,4

Função
DataFrame.agg(self, func, axis=0, *args, **kwargs)

permite a agregação de várias operações em um determinado eixo. Como parâmetros, a função recebe ** kwargs (argumentos nomeados, consulte o artigo no habr para obter detalhes ), que são uma coluna na qual a operação é executada e o nome da função de agregação entre aspas simples. A gravação parece bastante volumosa. Ir em frente.

A mesma solução usando expressões lambda parece muito mais concisa e simples:

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

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

Resultado:

Setosa 5,8 4,3 4,4 2,3 1,9 1,0 0,6 0,1
Versicolor 7,0 4,9 3,4 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

Frequentemente, ouço muito menos o que escrever quando Python ao resolver o mesmo tipo de problema em comparação com outros idiomas. Aqui, em comparação com o T-SQL, pode-se concordar com isso, mas a clareza e a sequência de expressões de ferramentas linguísticas como SQL ou T-SQL estão completamente perdidas (opinião pessoal).

Conjunto de dados e código do artigo pode ser encontrado aqui

O que há de novo no 0.25.0 (18 de Julho de 2019)

pandas

All Articles