Dataklargøring og eksplorativ dataanalyse
De lærende indlæser et rådatasæt, profilerer fordelinger og korrelationer, identificerer problemer med datakvaliteten og dokumenterer resultaterne i en reproducerbar Jupyter-notebook.
Dataklargøring og eksplorativ dataanalyse er en gratis Machine Learning Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Machine Learning Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Hvad er eksplorativ dataanalyse?
Eksplorativ dataanalyse (EDA) er en metode, hvor et datasæt profileres før modellering for at forstå dets struktur, fordelinger, sammenhænge og kvalitetsproblemer. Begrebet blev introduceret af John Tukey, og EDA følger et enkelt princip: lad dataene tale. Hvis du skynder dig forbi EDA og går direkte til modellering, er det den næsthyppigste årsag til, at ML-projekter mislykkes, kun overgået af dårlig problemafgrænsning. EDA forhindrer dig i at bygge modeller på et mangelfuldt grundlag.
Indlæsning og første gennemgang
Begynd altid med en strukturel gennemgang: Hvor mange rækker og kolonner er der, og hvilke datatyper bruges? Brug df.shape, df.dtypes, df.head() og df.info(). Se efter kolonner, der ser numeriske ud, men er gemt som object (strenge), samt kolonner, der ser kategoriske ud, men er kodet som heltal. Uoverensstemmende datatyper forårsager skjulte fejl senere i behandlingen, når scikit-learn behandler en heltalskodet kategori som en kontinuert variabel.
import pandas as pd
import numpy as np
# Load dataset
df = pd.read_csv('customer_churn.csv')
print('Shape:', df.shape)
print('\nData types:')
print(df.dtypes)
print('\nFirst 5 rows:')
print(df.head())
print('\nSummary info:')
df.info()Univariat analyse: fordelinger
Univariat analyse undersøger én variabel ad gangen. For numeriske funktioner skal du tegne histogrammer og beregne opsummerende statistikker (gennemsnit, median, standardafvigelse, skævhed). Meget skæve fordelinger (skævhed > 2) har ofte gavn af en logaritmisk transformation før modellering. For kategoriske funktioner skal du tegne søjlediagrammer over værdioptællinger. Kategorier, der forekommer i færre end 1 % af rækkerne, kan give problemer med one-hot-kodning og stratificeret opdeling.
import matplotlib.pyplot as plt
import seaborn as sns
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# Numeric: histogram of account age
df['account_age_days'].hist(bins=40, ax=axes[0])
axes[0].set_title('Account age distribution')
axes[0].set_xlabel('Days')
# Categorical: churn rate by plan type
df.groupby('plan_type')['churned'].mean().plot(kind='bar', ax=axes[1])
axes[1].set_title('Churn rate by plan type')
axes[1].set_ylabel('Churn rate')
plt.tight_layout()
plt.savefig('univariate.png', dpi=150)Tabel med opsummerende statistikker
df.describe() viser antal, gennemsnit, standardafvigelse, minimum, kvartiler og maksimum for hver numerisk kolonne. Undersøg tabellen grundigt: En maksimumværdi, der er mange størrelsesordener større end 99-percentilen, er et tegn på afvigende værdier. Et minimum på nul i en kolonne med »dage siden seneste køb« kan betyde, at kunden købte noget i dag — eller det kan være en markør for manglende data. Når du forstår disse særtilfælde, forebygger du skjulte fejl i den efterfølgende forbehandling.
stats = df.describe(percentiles=[0.01, 0.25, 0.5, 0.75, 0.99])
print(stats.T) # transpose for readability
# Flag suspicious columns
for col in df.select_dtypes(include='number').columns:
skew = df[col].skew()
pct99 = df[col].quantile(0.99)
max_val = df[col].max()
if max_val > 5 * pct99:
print(f'OUTLIER WARNING: {col} — max ({max_val:.1f}) >> 99th pct ({pct99:.1f}), skew={skew:.2f}')Analyse af manglende værdier
Manglende værdier skal profileres, før du træffer beslutninger om imputering. Beregn procentdelen af nuller pr. kolonne med df.isnull().mean(). Kolonner med mere end 50 % manglende data bør måske fjernes helt. Forstå mekanismen bag de manglende værdier: Er de helt tilfældigt manglende (MCAR), eller er de ikke tilfældigt manglende (MNAR) — f.eks. fordi kunder, der forlod virksomheden, slettede deres kontooplysninger? MNAR-manglende data er i sig selv informative og bør kodes som en binær indikator.
missing = df.isnull().mean().sort_values(ascending=False)
missing_pct = missing[missing > 0] * 100
print('Missing value percentages:')
print(missing_pct.round(1))
import matplotlib.pyplot as plt
missing_pct.plot(kind='barh', figsize=(8, 5))
plt.xlabel('% missing')
plt.title('Missing values by column')
plt.tight_layout()
plt.savefig('missing.png', dpi=150)Bivariat analyse: korrelationer
Bivariat analyse undersøger relationer mellem par af variabler. For relationer mellem numeriske variabler skal du beregne en korrelationsmatrix og visualisere den som et varmekort med seaborn.heatmap. Korrelationer over 0,95 mellem to funktioner er tegn på multikollinearitet — begge funktioner indeholder næsten identisk information, så den ene kan fjernes uden at miste forudsigelseskraft. Beregn også punkt-biseriale korrelationer mellem numeriske funktioner og det binære mål for på forhånd at identificere de mest forudsigende funktioner.
import seaborn as sns
import matplotlib.pyplot as plt
numeric_df = df.select_dtypes(include='number')
corr = numeric_df.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(corr, annot=True, fmt='.2f', cmap='coolwarm', center=0)
plt.title('Correlation matrix')
plt.tight_layout()
plt.savefig('corr_heatmap.png', dpi=150)
# Highest corr pairs (excluding self-correlation)
high_corr = (
corr.where(np.triu(np.ones(corr.shape), k=1).astype(bool))
.stack().abs().sort_values(ascending=False)
)
print('Top correlated pairs:')
print(high_corr.head(5))Analyse af målvariablen
Analyser altid målvariablen separat. Ved binær klassifikation skal du beregne andelen af positive klasser (df['churned'].mean()). Andele under 5 % eller over 95 % tyder på en alvorlig ubalance, som påvirker valg af algoritme og evalueringsmål. For regressionsmål skal du kontrollere normaliteten — skæve mål har ofte gavn af en logaritmisk transformation før træning, især for træbaserede modeller, som er robuste over for dette, men det er afgørende for lineær regression.
target = 'churned'
class_dist = df[target].value_counts(normalize=True)
print('Class distribution:')
print(class_dist)
print(f'\nPositive class rate: {df[target].mean():.3f}')
print(f'Imbalance ratio: {class_dist.max() / class_dist.min():.1f}:1')
# Visual
df[target].value_counts().plot(kind='bar')
import matplotlib.pyplot as plt
plt.title('Target class distribution')
plt.ylabel('Count')
plt.xticks([0, 1], ['Retained', 'Churned'], rotation=0)
plt.tight_layout()
plt.savefig('target_dist.png', dpi=150)Registrering og behandling af afvigende værdier
Afvigende værdier kan forvrænge modeltræningen, især for afstandsbaserede modeller (KNN, SVM) og lineær regression. Brug IQR-metoden (markér værdier uden for [Q1 - 1.5·IQR, Q3 + 1.5·IQR]) eller z-score (markér værdier med |z| > 3) til den indledende registrering. Undersøg hver markeret afvigende værdi: Er det en fejl ved dataindtastningen, en legitim ekstremværdi eller en sensorfejl? Legitime ekstremværdier bør beholdes; fejl bør rettes eller fjernes.
def iqr_outliers(series):
Q1, Q3 = series.quantile(0.25), series.quantile(0.75)
IQR = Q3 - Q1
lower, upper = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR
outlier_mask = (series < lower) | (series > upper)
return outlier_mask, lower, upper
for col in df.select_dtypes(include='number').columns:
mask, lo, hi = iqr_outliers(df[col])
n_out = mask.sum()
if n_out > 0:
print(f'{col}: {n_out} outliers ({n_out/len(df)*100:.1f}%), '
f'valid range=[{lo:.2f}, {hi:.2f}]')Diagrammer over relationen mellem funktioner og mål
Ved klassifikationsopgaver skal du visualisere, hvordan fordelingen af hver numerisk funktion varierer mellem klasserne, ved hjælp af et violinplot eller boksplot grupperet efter målet. Funktioner, hvor fordelingerne tydeligt adskiller de to klasser, er sandsynligvis forudsigende. For kategoriske funktioner viser et grupperet søjlediagram over frafaldsraten for hver kategoriværdi hurtigt, hvilke kategorier der er forbundet med højere risiko.
import seaborn as sns
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# Numeric feature vs target: violin plot
sns.violinplot(
data=df, x='churned', y='account_age_days',
palette=['#2196F3', '#F44336'], ax=axes[0]
)
axes[0].set_xticklabels(['Retained', 'Churned'])
axes[0].set_title('Account age by churn status')
# Categorical feature vs target: bar plot
df.groupby('plan_type')['churned'].mean().plot(kind='bar', ax=axes[1])
axes[1].set_title('Churn rate by plan type')
axes[1].set_ylabel('Churn rate')
plt.tight_layout()
plt.savefig('feature_target.png', dpi=150)Dokumentation af EDA-resultater
EDA-resultater skal dokumenteres i en reproducerbar Jupyter-notesbog, der deles med teamet. Som minimum skal du dokumentere: fjernede kolonner og årsagerne til det, beslutninger om imputering for hver kolonne, behandling af afvigende værdier, omfanget af klasseubalancen, de vigtigste forudsigende funktioner og eventuelle problemer med datakvaliteten, der er sendt videre til data engineering-teamet. Denne notesbog bliver datakvalitetsafsnittet i det endelige modelkort og er uvurderlig ved fejlfinding af regressioner i produktionen flere måneder senere.
# EDA findings summary (add as a markdown cell in the notebook)
findings = {
'dropped_columns': ['customer_id (identifier)', 'last_login_ip (PII, not predictive)'],
'imputation': {
'days_since_support_contact': 'median (12% missing, MCAR)',
'contract_end_days': 'mode (3% missing)'
},
'outliers': 'total_spend: 14 values > $50k capped at 99th percentile ($48,200)',
'class_imbalance': '8.3% churn rate — use SMOTE or class_weight=balanced',
'top_features': ['days_since_last_purchase', 'total_spend_90d', 'support_tickets'],
'escalations': ['contract_type column has 847 unmapped legacy codes — check with engineering']
}
for key, val in findings.items():
print(f'{key}: {val}')Automatiserede værktøjer til EDA
Ved store datasæt med hundredvis af funktioner er manuel EDA upraktisk. ydata-profiling (tidligere pandas-profiling) genererer en interaktiv HTML-rapport med fordelinger, korrelationer, manglende værdier og advarsler om afvigende værdier for hver kolonne med ét funktionskald. sweetviz opretter sammenligningsrapporter på tværs af opdelinger i trænings- og testdata eller segmenter af målklasser. Brug disse værktøjer som udgangspunkt, men følg altid op med domænespecifikke diagrammer for de vigtigste funktioner.
# ydata-profiling: one line EDA report
# pip install ydata-profiling
from ydata_profiling import ProfileReport
profile = ProfileReport(
df,
title='Customer Churn EDA Report',
explorative=True
)
profile.to_file('eda_report.html')
print('Report saved to eda_report.html')
# sweetviz: compare train vs test distribution
# pip install sweetviz
import sweetviz as sv
report = sv.analyze(df, target_feat='churned')
report.show_html('sweetviz_report.html')Hurtigt tjek
Test din forståelse af begreberne inden for Machine Learning with Python fra denne lektion.
Opsummering af lektionen
I denne lektion lærte du, at EDA profilerer fordelinger, relationer, manglende værdier og afvigende værdier før modellering, at bivariat analyse (korrelationer og diagrammer over funktioner og mål) identificerer de mest forudsigende funktioner, og at EDA-resultater skal dokumenteres i en reproducerbar notesbog for at understøtte beslutninger om forbehandling og fungere som dokumentation for datakvaliteten. Næste gang gennemfører vi en modelvalgsturnering for at sammenligne fem algoritmer på det samme behandlede datasæt.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “Dataklargøring og eksplorativ dataanalyse” gratis?
Ja — hele teksten til “Dataklargøring og eksplorativ dataanalyse” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Machine Learning Academy-kurset, skal du opgradere til CoddyKit PRO. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Dataklargøring og eksplorativ dataanalyse”?
De lærende indlæser et rådatasæt, profilerer fordelinger og korrelationer, identificerer problemer med datakvaliteten og dokumenterer resultaterne i en reproducerbar Jupyter-notebook. Du øver dig i Machine Learning Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Machine Learning Academy?
Der kræves ingen tidligere erfaring. Machine Learning Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Dataklargøring og eksplorativ dataanalyse”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Machine Learning Academy-lektion?
Ja. Alle Machine Learning Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Projektafgrænsning: Definition af problem og succeskriterier
- Dataklargøring og eksplorativ dataanalyse
- Turnering i modelvalg: Sammenlign fem algoritmer
- Pakning, dokumentation og præsentation af den endelige model