DataFrame.apply() și Series.apply() în pandas

Aplică o funcție pe fiecare valoare a unei coloane sau pe fiecare coloană / rând al unui tabel (axis=1 pentru rânduri).

Sintaxă
s.apply(func, args=(), *, by_row='compat', **kwargs)
df.apply(func, axis=0, raw=False, result_type=None, args=(), by_row='compat', engine=None, engine_kwargs=None, **kwargs)

Ce face DataFrame.apply() și Series.apply()

Series.apply(func) apelează funcția pentru fiecare valoare din coloană și pune rezultatele într-un Series nou. Este util când regula nu se poate scrie ca operație pe toată coloana, de exemplu un calificativ calculat cu if.

DataFrame.apply(func) trimite funcției câte o coloană întreagă (axis=0, implicit) sau, cu axis=1, câte un rând, ca Series în care valorile se citesc după numele coloanei: rand["nota"].

apply rulează o funcție Python pentru fiecare element, deci este mai lent decât operațiile pe coloane întregi. Pentru calcule simple (df["a"] + df["b"], df["nota"] * 2) nu ai nevoie de el.

Parametri

Parametru Descriere
func Funcția aplicată: o funcție definită cu def, o lambda sau o funcție încorporată (len, max).
axis (DataFrame) 0 sau "index" (implicit): funcția primește fiecare coloană; 1 sau "columns": fiecare rând.
args, **kwargs Argumente în plus trimise funcției.
result_type (DataFrame) "expand", "reduce", "broadcast": forma rezultatului când funcția returnează o listă.
raw (DataFrame) Dacă este True, funcția primește array-uri NumPy în loc de Series.

Ce returnează

Un Series sau un DataFrame, după ce returnează funcția.

Exemple

Exemplul 1: Series.apply cu o funcție proprie

import pandas as pd

note = pd.Series([9.5, 4.0, 7.5, 10.0], index=["Ana", "Mihai", "Ioana", "Elena"])

def calificativ(nota):
    if nota >= 9:
        return "foarte bine"
    if nota >= 5:
        return "promovat"
    return "nepromovat"

print(note.apply(calificativ))

Rezultat

Ana      foarte bine
Mihai     nepromovat
Ioana       promovat
Elena    foarte bine
dtype: str

Exemplul 2: Pe rânduri cu axis=1

Funcția primește fiecare rând și calculează media celor două note, cu un bonus pentru elevii din Iași (o regulă care combină mai multe coloane).

import pandas as pd

df = pd.DataFrame({
    "nume": ["Ana", "Mihai", "Ioana"],
    "oras": ["Iași", "Cluj", "Iași"],
    "mate": [9, 6, 8],
    "romana": [10, 7, 7],
})

def media(rand):
    m = (rand["mate"] + rand["romana"]) / 2
    if rand["oras"] == "Iași":
        m += 0.25
    return m

df["media"] = df.apply(media, axis=1)
print(df)

Rezultat

    nume  oras  mate  romana  media
0    Ana  Iași     9      10   9.75
1  Mihai  Cluj     6       7   6.50
2  Ioana  Iași     8       7   7.75

Exemplul 3: Pe coloane (axis=0)

Funcția primește fiecare coloană de note și returnează diferența dintre nota maximă și cea minimă.

import pandas as pd

note = pd.DataFrame({"mate": [9, 6, 8], "romana": [10, 7, 7]})
print(note.apply(lambda col: col.max() - col.min()))

Rezultat

mate      3
romana    3
dtype: int64

Greșeli frecvente

  • Uiți axis=1 când vrei să lucrezi pe rânduri: funcția primește coloane, iar rand["nota"] aruncă KeyError.
  • Folosești apply pentru calcule care merg direct pe coloană: df["total"] = df.apply(lambda r: r["pret"] * r["cant"], axis=1) este mult mai lent decât df["pret"] * df["cant"].
  • Pentru înlocuiri după un dicționar folosești apply; map face asta direct.

Comenzi înrudite

  • Series.map() și DataFrame.map(): Înlocuiește fiecare valoare după un dicționar sau o funcție (Series.map); DataFrame.map aplică o funcție pe fiecare celulă.
  • DataFrame.assign() și coloane noi: Adaugă coloane calculate: df[„col”] = … modifică tabelul, iar assign() returnează un tabel nou și acceptă funcții lambda.
  • agg() / aggregate(): Aplică mai multe funcții de agregare deodată, diferite pe coloane, cu nume alese de tine pentru coloanele rezultatului.
  • DataFrame.groupby(): Împarte tabelul în grupuri după una sau mai multe coloane, ca să calculezi totaluri, medii sau numărări pentru fiecare grup.