Pandas fillna i dropna: Vodič za rukovanje nedostajućim podacima u Pythonu (2026)
Praktični vodič za rukovanje NaN vrijednostima u pandasu 2.2: fillna, dropna, ffill, bfill i interpolate, s primjerima iz stvarnih projekata i smjernicama kada koja metoda ima smisla.
Funkcija fillna() u pandasu zamjenjuje nedostajuće (NaN) vrijednosti u DataFrame-u ili Series-u zadanom vrijednošću, a dropna() u potpunosti uklanja retke ili stupce koji sadrže NaN. Kombinacija ove dvije metode, zajedno s isna() za detekciju i interpolate() za pametno popunjavanje, čini standardni alat za čišćenje stvarnih skupova podataka. U ovom vodiču pokazujem kako ih koristim u pandasu 2.2, s pravim brojkama, edge case-ovima i smjernicama kada koja metoda ima smisla.
isna() i notna() vraćaju Boolean masku. Koristite .sum() za prebrojavanje NaN-ova po stupcu.
fillna(value) popunjava skalarom. fillna(method='ffill') je deprecirano u pandas 2.2, pa koristite ffill() i bfill() izravno.
dropna(how='any') uklanja redak ako bilo koji stupac ima NaN; how='all' samo ako su svi NaN; thresh=N zadržava retke s barem N ne-NaN vrijednosti.
Za numeričke serije vremena, interpolate(method='linear') daje bolje rezultate od konstantnog popunjavanja.
Od pandas 2.2 ne preporučuje se inplace=True u lančanim pozivima. Koristite df = df.fillna(...) za predvidljivo ponašanje (vidi pandas 2.2 release notes).
NaN se ne uspoređuje sam sa sobom: np.nan == np.nan vraća False, zato uvijek koristite isna().
Što je NaN u pandasu i odakle dolazi?
U pandasu, NaN (Not a Number) je specijalna float vrijednost iz NumPy-a koju knjižnica koristi kao univerzalni marker za nedostajuće podatke. Pojavljuje se kada CSV ima prazne ćelije, kada se baze podataka vraćaju s NULL vrijednostima, ili kada operacije poput merge, reindex i pivot proizvedu nepostojeće kombinacije ključeva.
Za datume pandas koristi NaT (Not a Time), a za nullable cjelobrojne i boolean tipove novi pd.NA (uveden u pandas 1.0, dorađen u 2.2). Svi se ponašaju slično pri filtriranju, ali se razlikuju u dtype-u rezultirajućeg stupca. To je važno kada DataFrame šaljete u bazu ili Parquet datoteku.
Pogledajmo kratak primjer kako NaN nastaje prirodno:
U izlazu ćete vidjeti NaN za brojeve, None (koji pandas tretira kao NaN) za stringove, i NaT za datum koji nedostaje. Dtype stupca potrosnja ostaje float64 jer NumPy NaN postoji samo unutar float reprezentacije.
Kako otkriti nedostajuće vrijednosti u DataFrame-u
Najčešća pogreška kod nedostajućih podataka? Usporedba s == np.nan. Ne radi. NaN nije jednak ni sam sebi prema IEEE 754 standardu. Umjesto toga koristite isna() ili njen alias isnull():
# Boolean maska istih dimenzija kao DataFrame
maska = df.isna()
# Broj NaN-ova po stupcu, najkorisniji prikaz na početku analize
print(df.isna().sum())
# Postotak nedostajućih vrijednosti
print((df.isna().mean() * 100).round(2))
# Redovi koji imaju barem jedan NaN
df[df.isna().any(axis=1)]
# Redovi bez ijednog NaN-a
df[df.notna().all(axis=1)]
Za brzu vizualnu inspekciju u Jupyter bilježnici, paket missingno daje toplotnu kartu nedostajućih vrijednosti, što je dosta korisno kad istražujete obrasce u stupcima. Ako tek čistite skup podataka od nule, preporučujem prvo proći kroz naš kompletni vodič za čišćenje podataka s pandasom jer postavlja kontekst za sve što slijedi.
fillna: popunjavanje nedostajućih vrijednosti
Najjednostavniji oblik je fillna(value) gdje je value skalar koji zamjenjuje sve NaN-ove:
# Sve NaN-ove zamijeni nulom
df_popunjen = df.fillna(0)
# Različita vrijednost po stupcu
df_popunjen = df.fillna({
"grad": "Nepoznato",
"potrosnja": df["potrosnja"].mean(),
"datum": pd.Timestamp("2026-01-01"),
})
# Popunjavanje samo na razini odabranog stupca
df["potrosnja"] = df["potrosnja"].fillna(df["potrosnja"].median())
Statistička pravila iz prakse: za simetrične numeričke stupce koristite mean(), za asimetrične ili one s outlierima median(), a za kategorijske vrijednosti mode()[0] ili eksplicitnu oznaku poput "Nepoznato". Honestly, mean popunjavanje smanjuje varijancu (što može oštetiti modele strojnog učenja), pa za regresijske modele razmislite o bibliotekama poput scikit-learn SimpleImputer ili IterativeImputer.
ffill i bfill: propagacija vrijednosti
Kada radite s vremenskim serijama, popunjavanje srednjom vrijednošću nema smisla. Bolje je propagirati posljednju poznatu vrijednost prema naprijed (ffill) ili sljedeću poznatu prema natrag (bfill):
cijene = pd.Series(
[100.0, np.nan, np.nan, 105.0, np.nan, 110.0],
index=pd.date_range("2026-06-01", periods=6, freq="D"),
)
# Propagiraj posljednju poznatu cijenu prema naprijed
cijene.ffill()
# Ograniči propagaciju na najviše 1 uzastopni NaN
cijene.ffill(limit=1)
# Kombinacija: prvo ffill, ostatak bfill
cijene.ffill().bfill()
Parametar limit sprječava ekstrapolaciju preko velikih praznina. Korisno kada nedostajući podaci znače stvarni prekid (npr. zatvoreni dan trgovanja vs. dugotrajno gašenje senzora). U jednom projektu s mjernim podacima senzora sam ovo zaboravio postaviti, pa je ffill tiho popunio tjedan dana mrtvih očitanja istom posljednjom vrijednošću. Otkrili smo to tek kad se anomalija pojavila u klijentovom izvještaju. Za naprednije popunjavanje obrazaca koji se mijenjaju kroz vrijeme, kombinirajte groupby s ffill kako je opisano u našem vodiču za pandas GroupBy.
dropna: uklanjanje redaka i stupaca
Ako popunjavanje nije primjereno (npr. u eksploratornoj analizi gdje želite samo cijele zapise), dropna() uklanja redove ili stupce s nedostajućim podacima:
# Ukloni svaki red koji ima barem jedan NaN (default je how='any')
df.dropna()
# Ukloni red samo ako su SVI stupci NaN
df.dropna(how="all")
# Ukloni red ako stupci 'potrosnja' i 'datum' nemaju vrijednost
df.dropna(subset=["potrosnja", "datum"])
# Zadrži samo retke s barem 3 ne-NaN vrijednosti
df.dropna(thresh=3)
# Ukloni stupce (umjesto redaka) koji imaju ikakav NaN
df.dropna(axis=1)
Parametar thresh je iznenađujuće moćan. Koristan je za uklanjanje gotovo praznih redaka iz raštrkanih (sparse) skupova podataka bez gubitka onih koji nose koristan signal. Uvijek provjerite koliko redaka gubite prije nego se obvežete: print(len(df), "→", len(df.dropna())).
Razlika između fillna i dropna
Najčešće pitanje početnika: kada popuniti, a kada brisati? Sljedeća tablica sažima ključne razlike:
Aspekt
fillna()
dropna()
Što radi
Zamjenjuje NaN konkretnom vrijednošću
Uklanja redove ili stupce s NaN-om
Veličina rezultata
Ista kao izvorni DataFrame
Manja (ili prazna)
Rizik gubitka informacija
Nizak; uvodi pristranost (bias)
Visok ako je puno NaN-ova
Tipičan slučaj
Strojno učenje, ETL produkcijski pipelinei
Brza eksplorativna analiza, mali postotak NaN-a
Promjena dtype-a
Može promijeniti (npr. int u float)
Čuva dtype
Performanse
O(n) bez realokacije
O(n) plus realokacija indeksa
Pravilo iz prakse: ako stupac ima <5% NaN-a i redovi su skupi za izgubiti, popunite. Ako stupac ima >40% NaN-a, razmislite o uklanjanju cijelog stupca jer popunjavanje samo izmišlja podatke. Između toga, odluku donesite na temelju ciljne metrike modela, a ne intuicije.
Interpolacija za numeričke i vremenske podatke
Za uređene numeričke serije (cijene, temperature, mjerenja senzora), interpolate() ispunjava praznine korištenjem matematičkog modela između susjednih poznatih vrijednosti:
temp = pd.Series(
[20.0, np.nan, np.nan, 23.0, 24.0, np.nan, 26.0],
index=pd.date_range("2026-06-20", periods=7, freq="D"),
)
# Linearna interpolacija (default)
temp.interpolate(method="linear")
# Vremenska interpolacija, uzima u obzir razmake u indeksu
temp.interpolate(method="time")
# Kubni splajn, gladak rezultat, traži scipy
temp.interpolate(method="cubic")
# Ograniči koliko uzastopnih NaN-ova se popunjava
temp.interpolate(limit=2, limit_direction="forward")
Metoda time je naročito važna ako vaš vremenski indeks nije ravnomjerno raspoređen. Recimo, dnevni podaci s vikendima koji nedostaju. linear bi u tom slučaju davao iste razlike između susjednih točaka neovisno o stvarnoj razlici u datumima, dok time proporcionalno raspodjeljuje razliku. Više detalja vidite u pandas User Guide poglavlju o missing data.
Nullable tipovi i pd.NA u pandas 2.2
Klasični NumPy int64 stupac ne može sadržavati NaN. Čim ubacite nedostajuću vrijednost, pandas tiho pretvara stupac u float64. Od pandasa 1.0 (i stabilno u 2.2), nullable dtypovi to rješavaju:
# Nullable integer (koristi pd.NA umjesto NaN)
s = pd.Series([1, 2, None, 4], dtype="Int64")
print(s.dtype) # Int64 (s velikim I)
print(s.isna()) # [False, False, True, False]
# Nullable boolean i string tipovi
b = pd.Series([True, None, False], dtype="boolean")
t = pd.Series(["a", None, "c"], dtype="string")
# Arrow-backed string tip (brži, manje memorije, pandas 2.0+)
t_arrow = pd.Series(["a", None, "c"], dtype="string[pyarrow]")
Nullable tipovi su preporučeni put kada DataFrame šaljete u Parquet, Arrow ili Postgres, jer čuvaju semantičku razliku između "nepoznato" i "nula". Mana? Neke biblioteke trećih strana (starije verzije scikit-learn, matplotlib) ne razumiju pd.NA, pa morate konvertirati natrag prije korištenja.
Česti problemi i kako ih izbjeći
1. NaN se "vraća" nakon merge-a
Nakon pd.merge(left, right, how='left'), redovi koji se ne podudaraju u desnom DataFrame-u dobivaju NaN za sve desne stupce. To nije bug, to je očekivano. Provjerite kvalitetu spajanja s indicator=True kako biste vidjeli koliko redaka je left_only.
2. SettingWithCopyWarning kod fillna
Ako vidite to upozorenje pri df[df['x'] > 0]['y'].fillna(0), problem je u lančanom indeksiranju. Koristite .loc: df.loc[df['x'] > 0, 'y'] = df.loc[df['x'] > 0, 'y'].fillna(0). Ovu sam grešku radio mjesecima dok mi nije sjelo zašto pandas tiho ne ažurira originalni okvir.
3. inplace=True je deprecirano u lancima
Od pandasa 2.2, lančani pozivi s inplace=True generiraju upozorenje jer Copy-on-Write postaje default u pandasu 3.0. Pišite df = df.fillna(0) umjesto df.fillna(0, inplace=True) i bit ćete sigurni prema budućnosti.
4. Razlika između None i NaN
U Python objektnim stupcima, None i np.nan oba se prikazuju kao "NaN" u izlazu, ali isinstance(x, float) ih razlikuje. isna() tretira oba kao nedostajuće, što je obično ono što želite.
5. Popunjavanje prije ili poslije agregacije?
Ako popunite NaN-ove nulom prije izračuna prosjeka, prosjek će biti niži nego ako koristite mean(skipna=True) (default). Pandas funkcije po defaultu preskaču NaN, pa koristite to umjesto preventivnog popunjavanja. Za napredne transformacije koje primjenjuju vlastitu logiku popunjavanja, pogledajte naš vodič o pandas apply, map i lambda funkcijama.
Često postavljana pitanja
Koja je razlika između NaN, None i NaT u pandasu?
NaN je float marker za nedostajući broj iz NumPy-a, None je Python-ov objekt koji pandas tretira kao NaN u objektnim stupcima, a NaT (Not a Time) označava nedostajući datum ili vrijeme. Funkcija isna() ih sve tretira jednako, kao "nedostajuće".
Kako popuniti NaN vrijednosti različitim vrijednostima po stupcu?
Proslijedite rječnik u fillna: df.fillna({"dob": df["dob"].median(), "grad": "Nepoznato"}). Pandas će svakom stupcu primijeniti odgovarajuću vrijednost, a stupce koji nisu u rječniku ostaviti netaknute.
Zašto fillna ne mijenja moj DataFrame?
Većina pandas metoda vraća novi objekt umjesto da mijenja izvornik. Spremite rezultat: df = df.fillna(0). Parametar inplace=True postoji, ali je u pandasu 2.2 depreciran za lančane pozive i postat će potpuno uklonjen u pandasu 3.0.
Kako izbrisati stupce s previše nedostajućih vrijednosti?
Filtrirajte stupce po pragu postotka: df = df.loc[:, df.isna().mean() < 0.4]. Ovo zadržava samo stupce gdje je manje od 40% vrijednosti NaN. Alternativno, koristite df.dropna(axis=1, thresh=int(0.6 * len(df))).
Trebam li popuniti NaN prije treniranja modela strojnog učenja?
Da, većina scikit-learn estimatora ne podržava NaN ulaze. Koristite SimpleImputer ili IterativeImputer unutar Pipeline-a kako bi se imputacija učila na trening skupu i konzistentno primjenjivala na testni skup. Izbjegavajte popunjavanje na cijelom datasetu prije podjele jer to uzrokuje data leakage.
Pandas .str akcesor vektorizira Python string metode nad DataFrame stupcima. Vodič pokriva contains, replace, split, extract i PyArrow StringDtype u pandas 3.0 s primjerima koda.
Praktičan vodič kroz razlike .loc i .iloc u Pandas 2.2 — primjeri koda, česte greške, boolean maske i savjeti za brže i sigurnije indeksiranje DataFrame-ova.
Naučite raditi s vremenskim serijama u pandasu — od DatetimeIndex-a i resample operacija, preko rolling i expanding prozora, do detekcije anomalija. Vodič ažuriran za pandas 3.0 s primjerima koda.