Datakvalitet: saknade värden, dubbletter, fel
Kunna hitta och hantera saknade värden, dubbletter och orimliga värden.
Förkunskaper
Intuition
Det sägs att dataarbete är 80 % av ett ML-projekt. Det stämmer ungefär, och det är inte tråkigt slit — det är där de flesta faktiska förbättringarna kommer ifrån.
Tre problem, i tur och ordning:
| Problem | Hur du hittar det |
|---|---|
| Saknade värden | df.isna().sum() — men också värden kodade som -1, 999, "okänt" |
| Dubbletter | df.duplicated().sum(), och dubbletter på nyckeln även när raderna skiljer sig |
| Orimligheter | describe(): åldrar på 200, negativa priser, datum i framtiden |
Den svåraste frågan är varför värdet saknas, för den avgör vad du får göra åt det.
| Typ | Betyder | Exempel |
|---|---|---|
| MCAR | saknas helt slumpmässigt | en sensor tappade paket |
| MAR | saknas beroende på något du kan se | yngre svarar oftare på webbenkäter |
| MNAR | saknas beroende på värdet självt | höginkomsttagare uppger inte lön |
MNAR är farligast: att fylla i medelvärdet där de högsta värdena saknas flyttar hela fördelningen nedåt, och gör analysen systematiskt fel.
Formellt
Strategier för saknade värden:
| Strategi | När | Risk |
|---|---|---|
| Ta bort raden | få saknade, MCAR | skevhet om inte MCAR; datasvinn |
| Ta bort kolumnen | > 50 % saknas och låg nytta | tappar signal |
| Medel/median | numeriskt, MCAR | minskar variansen artificiellt |
| Vanligaste värdet | kategoriskt | överdriver majoriteten |
| Modellbaserad (kNN, iterativ) | mönster finns i övriga kolumner | dyrt; kan läcka |
| Indikatorkolumn + ifyllning | nästan alltid ett bra komplement | ingen |
Den sista raden förtjänar att framhållas: lägg till en kolumn x_saknades med 0/1 utöver ifyllningen. Att ett värde saknas är ofta i sig informativt — en patient utan provsvar skiljer sig från en med normalt provsvar — och modellen får då använda den informationen i stället för att luras av det ifyllda värdet.
Den viktigaste regeln om ifyllning: beräkna medelvärdet på träningsdatan och tillämpa det på validering och test. Räknar du medelvärdet över hela datasetet har du läckt information från testmängden in i träningen. Samma sak gäller skalning och kodning.
Dubbletter är inte alltid fel. Två identiska rader kan vara två verkliga händelser. Kontrollera alltid på nyckeln:
df.duplicated().sum() # helt identiska rader
df.duplicated(subset=["elev_id"]).sum() # samma nyckel, kanske olika data
Den andra raden hittar det verkligt problematiska fallet: två poster för samma person med olika uppgifter. Då måste någon avgöra vilken som gäller.
Dokumentera varje beslut. En rad per åtgärd, i kod eller en loggfil: vad som ändrades, hur många rader, och varför. Om sex månader kommer någon — troligen du — att undra varför det finns 4 812 rader i stället för 5 000.
Kod
import pandas as pd, numpy as np
df = pd.DataFrame({
"id": [1, 2, 3, 3, 5, 6],
"alder": [15, 16, 999, 999, -1, 17],
"poang": [80.0, np.nan, 70.0, 70.0, 65.0, np.nan],
"stad": ["Malmö", "malmö", "Lund", "Lund", "MALMÖ", "Lund "],
})
logg = []
def atgard(text, fore, efter):
logg.append(f"{text}: {fore} → {efter} rader")
# 1. Sentinelvärden är saknade värden i förklädnad
n = len(df)
df["alder"] = df["alder"].replace({999: np.nan, -1: np.nan})
print(df["alder"].isna().sum(), "åldrar saknas i själva verket") # 3
# 2. Dubbletter — både identiska rader och på nyckeln
fore = len(df)
df = df.drop_duplicates()
atgard("identiska dubbletter", fore, len(df))
print("dubbletter på id:", df.duplicated(subset=["id"]).sum()) # 0
# 3. Normalisera kategorier innan du räknar unika värden
df["stad"] = df["stad"].str.strip().str.lower()
print(sorted(df["stad"].unique())) # ['lund', 'malmö']
# 4. Indikator + ifyllning, med medelvärde FRÅN TRÄNINGSDATAN
train, test = df.iloc[:3].copy(), df.iloc[3:].copy()
for d in (train, test):
d["poang_saknades"] = d["poang"].isna().astype(int)
medel = train["poang"].mean() # ← beräknas bara på träningsdatan
train["poang"] = train["poang"].fillna(medel)
test["poang"] = test["poang"].fillna(medel)
print("\n".join(logg))
# identiska dubbletter: 6 → 5 rader
Indikatorkolumnen poang_saknades kostar ingenting och räddar ofta modellen: utan den ser ett ifyllt medelvärde ut som ett verkligt medelvärde.
Behärskning innebär
- Hittar saknade värden, dubbletter och orimligheter
- Väljer hanteringsstrategi medvetet
- Dokumenterar varje åtgärd
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- pandas — User Guide (BSD-3) — BSD-3-Clause
- scikit-learn User Guide (BSD-3) — BSD-3-Clause
- Statistiska centralbyrån — kvalitet i statistiken — myndighetsmaterial