Pandas & NumPy Academy · Lezione

Trasformazione e filtro con GroupBy

Usi transform() per aggiungere a una colonna statistiche a livello di gruppo e filter() per mantenere solo i gruppi che soddisfano una condizione.

Lezione 4 di 413 passaggi

Trasformazione e filtro con GroupBy è una lezione Pandas & NumPy Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Pandas & NumPy Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Pandas & NumPy Academy include 4 lezioni in totale.

Oltre l'aggregazione

Dopo aver acquisito dimestichezza con agg(), la domanda naturale è: cosa fare se si desidera mantenere tutte le righe originali arricchendole con statistiche a livello di gruppo? Oppure mantenere solo i gruppi che soddisfano una condizione? È qui che entrano in gioco transform() e filter(). Questi due metodi estendono GroupBy oltre il semplice riepilogo, introducendolo nell'ingegneria delle feature e nella selezione dei dati.

Capire transform()

transform() applica una funzione a ogni gruppo e restituisce un risultato con la stessa forma del DataFrame originale, ovvero un valore per ogni riga originale. Il risultato del gruppo viene ridistribuito a ogni riga appartenente a quel gruppo. Questo lo rende ideale per aggiungere statistiche a livello di gruppo come nuove colonne senza modificare il numero di righe.

import pandas as pd

df = pd.DataFrame({
    'dept':   ['Eng', 'HR', 'Eng', 'HR', 'Eng'],
    'salary': [90000, 60000, 95000, 62000, 88000]
})

# Add a column with each employee's department average salary
df['dept_avg'] = df.groupby('dept')['salary'].transform('mean')
print(df)
#    dept  salary    dept_avg
# 0   Eng   90000  91000.000
# 1    HR   60000  61000.000
# 2   Eng   95000  91000.000
# 3    HR   62000  61000.000
# 4   Eng   88000  91000.000

Casi d'uso comuni di transform()

Tra gli usi comuni di transform() vi sono: aggiungere la media del gruppo per normalizzare i valori, aggiungere la somma del gruppo per calcolare la percentuale del totale rappresentata da ogni riga e aggiungere il rango nel gruppo per confrontare ogni elemento con gli altri del proprio gruppo. Tutte queste operazioni mantengono la forma e l'indice originali, quindi il risultato può essere usato immediatamente insieme alle colonne originali.

# Percentage of each employee's salary within their department total
df['pct_of_dept'] = (
    df['salary'] / df.groupby('dept')['salary'].transform('sum') * 100
).round(1)
print(df[['dept', 'salary', 'pct_of_dept']])
# dept  salary  pct_of_dept
# Eng   90000        33.1
# HR    60000        49.2
# Eng   95000        34.9

Usare una funzione personalizzata in transform()

Come agg(), anche transform() accetta qualsiasi funzione chiamabile, oltre ai nomi stringa. La funzione riceve una Series di valori per un gruppo e deve restituire una Series della stessa lunghezza oppure uno scalare, che viene poi ridistribuito. Restituire uno scalare è il caso d'uso più comune; restituire una Series di lunghezza diversa genera un errore.

# Z-score normalisation within each department
def zscore(s):
    return (s - s.mean()) / s.std()

df['salary_zscore'] = df.groupby('dept')['salary'].transform(zscore)
print(df[['dept', 'salary', 'salary_zscore']].round(2))
# dept  salary  salary_zscore
# Eng   90000          -0.51
# HR    60000          -0.71
# Eng   95000           1.03

agg() e transform() a confronto

La differenza fondamentale è la seguente: agg() riduce il numero di righe, una per gruppo, mentre transform() mantiene il numero di righe, una per ogni riga originale. Usi agg() per creare una tabella riepilogativa. Usi transform() per aggiungere informazioni a livello di gruppo come nuova colonna nel DataFrame originale.

g = df.groupby('dept')['salary']

# agg: 2 rows (one per unique dept)
print(g.agg('mean'))
# dept
# Eng    91000.0
# HR     61000.0

# transform: 5 rows (one per original row)
print(g.transform('mean'))
# 0    91000.0
# 1    61000.0
# 2    91000.0
# 3    61000.0
# 4    91000.0

Capire filter()

filter() mantiene o scarta interi gruppi in base a una funzione booleana. Si passa una funzione che riceve un sotto-DataFrame relativo a un gruppo e restituisce True per mantenere il gruppo oppure False per eliminarlo. Il risultato è un sottoinsieme del DataFrame originale contenente solo le righe dei gruppi che hanno superato il test.

df2 = pd.DataFrame({
    'dept':   ['Eng', 'HR', 'Eng', 'HR', 'Eng', 'Legal'],
    'salary': [90000, 60000, 95000, 62000, 88000, 70000]
})

# Keep only departments with at least 2 employees
big_depts = df2.groupby('dept').filter(lambda g: len(g) >= 2)
print(big_depts)
# dept, salary rows: Eng(3) and HR(2) remain; Legal(1) dropped

Filtrare in base al valore aggregato del gruppo

Un uso molto comune di filter() consiste nel mantenere i gruppi il cui valore aggregato soddisfa una soglia. Ad esempio, può mantenere solo i reparti in cui lo stipendio medio supera un obiettivo oppure solo le categorie di prodotto con vendite totali superiori a un minimo. In questo modo può rimuovere i gruppi con pochi dati prima di procedere con ulteriori analisi.

# Keep only departments where average salary > 80000
high_paying = df2.groupby('dept').filter(
    lambda g: g['salary'].mean() > 80000
)
print(high_paying)
#    dept  salary
# 0   Eng   90000
# 2   Eng   95000
# 4   Eng   88000
# (HR avg is 61000, filtered out)

Combinare transform() e filter()

È possibile applicare transform() e filter() in sequenza per arricchire i dati e poi restringerli. Utilizzi prima filter() per rimuovere i gruppi irrilevanti, quindi applichi transform() al risultato filtrato per aggiungere feature a livello di gruppo. La combinazione produce un sottoinsieme pulito e ricco di feature, pronto per la modellazione o la reportistica.

# Step 1: keep only large departments
filtered = df2.groupby('dept').filter(lambda g: len(g) >= 2)

# Step 2: add group mean salary to the filtered result
filtered = filtered.copy()
filtered['dept_avg'] = filtered.groupby('dept')['salary'].transform('mean')
print(filtered)

transform() per il riempimento in avanti nei gruppi

transform() è utile anche con funzioni non numeriche. Un approccio diffuso consiste nel riempire i valori mancanti all'interno di un gruppo usando il riempimento in avanti o la mediana del gruppo, soluzione molto più efficace rispetto a un riempimento globale. Passi una lambda che chiama fillna() sulla Series del gruppo: il risultato avrà lo stesso indice del DataFrame originale.

import numpy as np

df3 = pd.DataFrame({
    'dept':   ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
    'salary': [90000, np.nan, 60000, np.nan, 88000]
})

# Fill NaN with the group mean
df3['salary_filled'] = df3.groupby('dept')['salary'].transform(
    lambda s: s.fillna(s.mean())
)
print(df3)

Approccio pratico: posizione relativa

Un potente caso d'uso aziendale consiste nel calcolare la posizione di ogni riga rispetto al proprio gruppo. Combinando transform() con operazioni aritmetiche, può aggiungere colonne come: stipendio meno la media del gruppo (scostamento), stipendio come frazione del totale del gruppo oppure un flag booleano che indica se il dipendente guadagna più della mediana del gruppo. Queste feature sono estremamente utili per dashboard e modelli ML.

df['dept_total'] = df.groupby('dept')['salary'].transform('sum')
df['pct_of_total'] = (df['salary'] / df['dept_total'] * 100).round(1)
df['above_avg'] = df['salary'] > df.groupby('dept')['salary'].transform('mean')
print(df[['dept', 'salary', 'pct_of_total', 'above_avg']])

Considerazioni sulle prestazioni

Sia transform() sia filter(), quando usati con funzioni stringa integrate, sono veloci perché sfruttano percorsi di esecuzione ottimizzati. Tuttavia, quando si passa una lambda o una funzione Python personalizzata, Pandas deve chiamare quella funzione una volta per gruppo, operazione che può essere lenta su dati con molti gruppi. Per ottenere le massime prestazioni con dataset di grandi dimensioni, verifichi se la logica personalizzata può essere espressa usando invece una funzione stringa integrata.

# Slower: custom lambda (called once per group)
df['dept_mean_slow'] = df.groupby('dept')['salary'].transform(lambda s: s.mean())

# Faster: built-in string shortcut (vectorised C path)
df['dept_mean_fast'] = df.groupby('dept')['salary'].transform('mean')

# Both give identical results, but the built-in is significantly faster

Verifica rapida

Verifichi la Sua comprensione di transform() e filter() di GroupBy presentati in questa lezione.

Riepilogo della lezione

In questa lezione ha imparato che transform() restituisce statistiche di gruppo ridistribuite fino al numero di righe originale, risultando ideale per aggiungere feature a livello di gruppo; che filter() mantiene o rimuove interi gruppi in base a una condizione booleana; e che la combinazione dei due metodi consente di creare dataset ricchi e filtrati per le analisi successive. Nella prossima lezione esploreremo come combinare i DataFrame usando pd.concat.

Gratis per iniziare

Impara Python con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
30
Lezioni
120

Domande Frequenti

La lezione «Trasformazione e filtro con GroupBy» è gratuita?

Sì — il testo completo di «Trasformazione e filtro con GroupBy» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Pandas & NumPy Academy, passa a CoddyKit PRO. Il corso Pandas & NumPy Academy include 4 lezioni in totale.

Cosa imparerò in «Trasformazione e filtro con GroupBy»?

Usi transform() per aggiungere a una colonna statistiche a livello di gruppo e filter() per mantenere solo i gruppi che soddisfano una condizione. Eserciti Pandas & NumPy Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Pandas & NumPy Academy?

Non è richiesta alcuna esperienza precedente. Pandas & NumPy Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Trasformazione e filtro con GroupBy»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Pandas & NumPy Academy?

Sì. Ogni lezione Pandas & NumPy Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Il pattern Split-Apply-Combine
  2. GroupBy con una o più chiavi
  3. Il metodo agg()
  4. Trasformazione e filtro con GroupBy
← Torna a Pandas & NumPy Academy