Ce face groupby().transform()
agg() reduce fiecare grup la un singur rând. transform() calculează același lucru, dar returnează un rezultat de aceeași lungime ca tabelul inițial: fiecare rând primește valoarea grupului lui. De aceea rezultatul se poate pune direct într-o coloană nouă.
Folosiri obișnuite: procentul pe care îl are fiecare vânzare din totalul orașului, diferența dintre nota unui elev și media clasei, sau completarea valorilor lipsă cu media grupului.
Funcția poate fi un nume ("sum", "mean", "count", "max") sau o funcție care primește o serie și întoarce o serie de aceeași lungime ori o singură valoare.
Parametri
| Parametru | Descriere |
|---|---|
func |
Funcția aplicată fiecărui grup: un șir ("sum", "mean", "rank", "cumsum") sau o funcție Python. |
*args, **kwargs |
Argumente transmise mai departe funcției. |
Ce returnează
O Series (sau un DataFrame) cu același index ca datele inițiale, deci se aliniază rând cu rând cu tabelul.
Exemple
Exemplul 1: Procentul fiecărei vânzări din totalul orașului
transform("sum") pune totalul orașului pe fiecare rând. Împărțind suma la el obții procentul. În Iași, 1200 din 1950 lei înseamnă 61,5%.
import pandas as pd
df = pd.DataFrame({
"oras": ["Iași", "Cluj", "Iași", "Cluj", "Iași"],
"vanzator": ["Ana", "Mihai", "Ioana", "Elena", "Radu"],
"suma": [1200, 800, 450, 1200, 300],
})
df["total_oras"] = df.groupby("oras")["suma"].transform("sum")
df["procent"] = (df["suma"] / df["total_oras"] * 100).round(1)
print(df)
Rezultat
oras vanzator suma total_oras procent
0 Iași Ana 1200 1950 61.5
1 Cluj Mihai 800 2000 40.0
2 Iași Ioana 450 1950 23.1
3 Cluj Elena 1200 2000 60.0
4 Iași Radu 300 1950 15.4
Exemplul 2: Diferența față de media clasei
Media clasei 9A este 8, iar a clasei 9B este 7. Scăzând media grupului vezi cine e peste sau sub media clasei lui.
import pandas as pd
df = pd.DataFrame({
"elev": ["Ana", "Mihai", "Ioana", "Radu", "Elena", "Dan"],
"clasa": ["9A", "9A", "9A", "9B", "9B", "9B"],
"nota": [9, 7, 8, 6, 8, 7],
})
media = df.groupby("clasa")["nota"].transform("mean")
df["fata_de_medie"] = df["nota"] - media
print(df)
Rezultat
elev clasa nota fata_de_medie
0 Ana 9A 9 1.0
1 Mihai 9A 7 -1.0
2 Ioana 9A 8 0.0
3 Radu 9B 6 -1.0
4 Elena 9B 8 1.0
5 Dan 9B 7 0.0
Exemplul 3: Completarea notelor lipsă cu media clasei
Rezultatul lui transform are aceeași lungime ca tabelul, deci poate fi dat lui fillna(): fiecare valoare lipsă primește media clasei ei.
import pandas as pd
df = pd.DataFrame({
"elev": ["Ana", "Mihai", "Ioana", "Radu", "Elena"],
"clasa": ["9A", "9A", "9B", "9B", "9B"],
"nota": [9.0, None, 6.0, None, 8.0],
})
media_clasei = df.groupby("clasa")["nota"].transform("mean")
df["nota"] = df["nota"].fillna(media_clasei)
print(df)
Rezultat
elev clasa nota
0 Ana 9A 9.0
1 Mihai 9A 9.0
2 Ioana 9B 6.0
3 Radu 9B 7.0
4 Elena 9B 8.0
Greșeli frecvente
- Folosești
agg("sum")și încerci să-l pui ca o coloană nouă: rezultatul are un rând pe grup, nu pe rând, iar coloana iese plină deNaN. Pentru o valoare pe fiecare rând ai nevoie detransform. - Dai lui
transformo funcție care întoarce o serie de altă lungime (de exemplu filtrează valori). Funcția trebuie să întoarcă o valoare sau o serie de aceeași lungime ca grupul. - Aplici
transformpe tot grupul (df.groupby("clasa").transform("mean")) când ai și coloane de text: media pe text dă eroare. Alege întâi coloana:["nota"].
Comenzi înrudite
DataFrame.groupby(): Împarte tabelul în grupuri după una sau mai multe coloane, ca să calculezi totaluri, medii sau numărări pentru fiecare grup.agg() / aggregate(): Aplică mai multe funcții de agregare deodată, diferite pe coloane, cu nume alese de tine pentru coloanele rezultatului.fillna() / ffill() / bfill(): Completează valorile lipsă cu o valoare fixă, cu valori diferite pe coloane, cu media sau cu valoarea anterioară ori următoare.DataFrame.assign() și coloane noi: Adaugă coloane calculate: df[„col”] = … modifică tabelul, iar assign() returnează un tabel nou și acceptă funcții lambda.