Missing data is the hole in a column where a value should be. pandas marks it with a sentinel — NaN for numbers, NaT for datetimes, None for objects — and gives you three moves: find it, drop it, or fill it. Each move costs something statistically.
Where you meet it
- Survey and sensor data — skipped questions, dropped readings, failed joins.
- Merging frames — a key in the left table with no match on the right becomes
NaN. - The first rows after a
shift(),pct_change(), or rolling window. - Any real dataset — clean data is the exception, not the rule.
What it does
A missing value is not zero and not an empty string — it is the explicit absence of information. How you handle it changes your sample: dropping shrinks it and can bias it; filling (imputation) keeps the shape but injects values you made up. The honest first step is to detect and count, then choose with the missingness mechanism in mind.
Drop and you may bias the sample; fill with the mean and you fake certainty that shrinks the variance. There is no free repair.
How it works
Under the hood, NaN is an IEEE-754 floating-point value (float('nan')). That is why a single NaN silently turns an integer column into float64. Detect missingness with isna(), then drop or fill:
import pandas as pd, numpy as np
df = pd.DataFrame({'age': [34, np.nan, 41, 23]})
df.isna() # boolean mask, True where missing
df.isna().sum() # count per column — always look first
df.dropna() # delete every row with any NaN
df['age'].fillna(df['age'].mean()) # mean imputation
df['age'].fillna(df['age'].median()) # median — robust to outliers
df['age'].ffill() # forward-fill: carry the last value down
For modelling, scikit-learn's SimpleImputer(strategy='mean') does the same fill but as a transformer you can fit on train data and transform on test — so the imputed value is learned once, not leaked from the test set.
Watch out
NaN != NaN. By the IEEE rule,NaNequals nothing, even itself — sodf == np.nannever matches. Always useisna()/notna().- dropna distorts the sample. It only gives an unbiased subset if data are Missing Completely At Random (MCAR); otherwise the rows you keep are systematically different.
- Mean imputation shrinks variance. Plugging the mean into every gap pulls the distribution toward its centre, deflating the standard deviation and correlations — the fix looks tidy but the statistics lie.
- One
NaNupcasts the column. An int column with a single missing value becomesfloat64(use the nullableInt64dtype to keep integers).
Go deeper
Fehlende Daten sind das Loch in einer Spalte, wo ein Wert stehen sollte. pandas markiert es mit einem Sentinel — NaN für Zahlen, NaT für Datetimes, None für Objekte — und bietet drei Wege: finden, löschen oder füllen. Jeder Weg hat statistisch seinen Preis.
Wo es vorkommt
- Umfrage- und Sensordaten — übersprungene Fragen, ausgefallene Messungen, fehlgeschlagene Joins.
- Merge von Frames — ein Schlüssel links ohne Treffer rechts wird zu
NaN. - Die ersten Zeilen nach
shift(),pct_change()oder einem Rolling Window. - Jeder echte Datensatz — saubere Daten sind die Ausnahme, nicht die Regel.
Was es tut
Ein fehlender Wert ist nicht Null und kein leerer String — er ist das explizite Fehlen von Information. Wie du damit umgehst, verändert deine Stichprobe: Löschen verkleinert und verzerrt sie womöglich; Füllen (Imputation) behält die Form, schleust aber erfundene Werte ein. Der ehrliche erste Schritt ist Erkennen und Zählen — und dann mit Blick auf den Fehlmechanismus entscheiden.
Löschen verzerrt womöglich die Stichprobe, mit dem Mittelwert füllen täuscht eine Sicherheit vor, die die Varianz drückt. Kostenlose Reparatur gibt es nicht.
Wie es funktioniert
Intern ist NaN ein IEEE-754-Gleitkommawert (float('nan')). Genau deshalb macht ein einzelnes NaN aus einer Integer-Spalte klammheimlich eine float64-Spalte. Fehlwerte findest du mit isna(), dann löschen oder füllen:
import pandas as pd, numpy as np
df = pd.DataFrame({'age': [34, np.nan, 41, 23]})
df.isna() # Boolean-Maske, True wo fehlend
df.isna().sum() # Anzahl pro Spalte — immer zuerst schauen
df.dropna() # jede Zeile mit irgendeinem NaN löschen
df['age'].fillna(df['age'].mean()) # Mittelwert-Imputation
df['age'].fillna(df['age'].median()) # Median — robust gegen Ausreißer
df['age'].ffill() # Forward-Fill: letzten Wert nach unten ziehen
Fürs Modellieren macht scikit-learns SimpleImputer(strategy='mean') dasselbe Füllen, aber als Transformer: fit auf den Trainingsdaten, transform auf den Testdaten — der Imputationswert wird einmal gelernt und nicht aus dem Testset geleakt.
Worauf achten
NaN != NaN. Nach der IEEE-Regel istNaNmit nichts gleich, nicht einmal mit sich selbst —df == np.nantrifft also nie. Immerisna()/notna()nutzen.- dropna verzerrt die Stichprobe. Eine unverzerrte Teilstichprobe liefert es nur, wenn die Daten Missing Completely At Random (MCAR) sind; sonst sind die behaltenen Zeilen systematisch anders.
- Mittelwert-Imputation senkt die Varianz. Den Mittelwert in jede Lücke zu setzen zieht die Verteilung zur Mitte, drückt Standardabweichung und Korrelationen — sieht aufgeräumt aus, aber die Statistik lügt.
- Ein
NaNhebt den Spaltentyp an. Eine Int-Spalte mit nur einem Fehlwert wird zufloat64(mit dem nullable DtypeInt64bleiben es Integer).