Machine Learning Academy · Lektion

Databearbetning och explorativ dataanalys

Ni läser in ett rådataset, analyserar fördelningar och korrelationer, identifierar problem med datakvaliteten och dokumenterar resultaten i en reproducerbar Jupyter-anteckningsbok.

Lektion 2 av 413 steg

Databearbetning och explorativ dataanalys är en gratis lektion i Machine Learning Academy på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Machine Learning Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Machine Learning Academy innehåller totalt 4 lektioner.

Vad är explorativ dataanalys?

Explorativ dataanalys (EDA) innebär att profilera ett dataset före modellering för att förstå dess struktur, fördelningar, samband och kvalitetsproblem. Begreppet myntades av John Tukey och EDA bygger på en enkel princip: låt data tala. Att skynda förbi EDA och gå direkt till modellering är den näst vanligaste orsaken till att ML-projekt misslyckas, efter bristfällig problemavgränsning. EDA hindrar er från att bygga modeller på bristfälliga grunder.

Laddning och första granskning

Börja alltid med en strukturell granskning: hur många rader och kolumner finns det, och vilka datatyper används? Använd df.shape, df.dtypes, df.head() och df.info(). Leta efter kolumner som verkar numeriska men lagras som object (strängar), samt kolumner som verkar kategoriska men är kodade som heltal. Felaktiga datatyper orsakar tysta fel längre fram när scikit-learn behandlar en heltalskodad kategori som en kontinuerlig 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 analys: fördelningar

Univariat analys undersöker en variabel i taget. För numeriska egenskaper ritar ni histogram och beräknar sammanfattande statistik (medelvärde, median, standardavvikelse, skevhet). Kraftigt skeva fördelningar (skevhet > 2) gynnas ofta av en logaritmisk transformering före modellering. För kategoriska egenskaper ritar ni stapeldiagram över värdefrekvenser. Kategorier som förekommer i färre än 1 % av raderna kan orsaka problem med one-hot-kodning och stratifierad uppdelning.

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)

Tabell med sammanfattande statistik

df.describe() producerar antal, medelvärde, standardavvikelse, minsta värde, kvartiler och maximalt värde för varje numerisk kolumn. Granska resultatet noggrant: ett maximalt värde som är flera storleksordningar högre än den 99:e percentilen signalerar avvikande värden. Ett minvärde på noll i en kolumn med ”dagar sedan senaste köp” kan betyda att kunden handlade i dag – eller vara en platshållare för saknade data. Genom att förstå dessa specialfall förhindrar ni tysta fel i den fortsatta förbehandlingen.

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}')

Analys av saknade värden

Saknade värden måste profileras innan beslut om imputering fattas. Beräkna andelen nullvärden per kolumn med df.isnull().mean(). Kolumner där mer än 50 % saknas kan behöva tas bort helt. Förstå mekanismen bakom de saknade värdena: är de helt slumpmässigt saknade (MCAR), eller är de inte slumpmässigt saknade (MNAR) – exempelvis att kunder som lämnat tjänsten raderade sin kontoinformation? MNAR är i sig informativt och bör kodas 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 analys: korrelationer

Bivariat analys undersöker samband mellan par av variabler. För samband mellan numeriska variabler beräknar ni en korrelationsmatris och visualiserar den som en värmekarta med seaborn.heatmap. Korrelationer över 0.95 mellan två egenskaper signalerar multikollinearitet – båda egenskaperna innehåller nästan samma information, så den ena kan tas bort utan att den prediktiva förmågan går förlorad. Beräkna även punkt-biseriala korrelationer mellan numeriska egenskaper och det binära målet för att tidigt identifiera de mest prediktiva egenskaperna.

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))

Analys av målvariabeln

Analysera alltid målvariabeln separat. För binär klassificering beräknar ni andelen positiva klasser (df['churned'].mean()). Andelar under 5 % eller över 95 % visar på en allvarlig obalans som påverkar val av algoritm och utvärderingsmått. För regressionsmål ska ni kontrollera normalfördelning – skeva målvariabler gynnas ofta av en logaritmisk transformering före träning, särskilt för träd-baserade modeller som är immuna mot detta, men transformeringen är kritisk för linjä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)

Detektering och hantering av avvikande värden

Avvikande värden kan förvränga modellträningen, särskilt för avståndsbaserade modeller (KNN, SVM) och linjär regression. Använd IQR-metoden (flagga värden utanför [Q1 - 1.5·IQR, Q3 + 1.5·IQR]) eller z-poäng (flagga värden där |z| > 3) för den inledande detekteringen. Undersök varje flaggat avvikande värde: beror det på ett inmatningsfel, är det ett legitimt extremvärde eller ett sensorfel? Legitimt extrema värden ska behållas; fel ska korrigeras eller tas bort.

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}]')

Diagram över samband mellan egenskaper och mål

För klassificeringsuppgifter visualiserar ni hur fördelningen för varje numerisk egenskap skiljer sig mellan klasserna med ett violinplot eller boxplot grupperat efter målet. Egenskaper där fördelningarna tydligt skiljer de två klasserna åt är sannolikt prediktiva. För kategoriska egenskaper visar ett grupperat stapeldiagram över andelen kundbortfall per kategori snabbt vilka kategorier som är förknippade med högre risk.

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)

Dokumentera EDA-resultat

EDA-resultat måste dokumenteras i en reproducerbar Jupyter-anteckningsbok som delas med teamet. Dokumentera åtminstone: vilka kolumner som togs bort och varför, beslut om imputering per kolumn, hantering av avvikande värden, omfattningen av klassobalansen, de viktigaste prediktiva egenskaperna samt eventuella datakvalitetsproblem som har eskalerats till data engineering-teamet. Anteckningsboken blir datakvalitetsavsnittet i det framtida modellkortet och är ovärderlig vid felsökning av regressionsproblem i produktion flera månader senare.

# 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}')

Automatiserade EDA-verktyg

För stora dataset med hundratals egenskaper är manuell EDA opraktisk. ydata-profiling (tidigare pandas-profiling) genererar en interaktiv HTML-rapport med fördelningar, korrelationer, saknade värden och varningar om avvikande värden för varje kolumn genom ett enda funktionsanrop. sweetviz skapar jämförelserapporter för uppdelningar av tränings- och testdata eller segment av målklasser. Använd dessa som utgångspunkt, men komplettera alltid med domänspecifika diagram för de viktigaste egenskaperna.

# 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')

Snabbkontroll

Testa era kunskaper om begreppen Machine Learning with Python från den här lektionen.

Sammanfattning av lektionen

I den här lektionen har ni lärt er att EDA profilerar fördelningar, samband, saknade värden och avvikande värden före all modellering, att bivariat analys (korrelationer och diagram över samband mellan egenskaper och mål) identifierar de mest prediktiva egenskaperna samt att EDA-resultat måste dokumenteras i en reproducerbar anteckningsbok för att vägleda beslut om förbehandling och fungera som dokumentation av datakvaliteten. Nästa steg är en modellvalsturnering där vi jämför fem algoritmer på samma bearbetade dataset.

Gratis att börja

Lär dig Python med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Databearbetning och explorativ dataanalys” gratis?

Ja – hela texten till ”Databearbetning och explorativ dataanalys” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Machine Learning Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Machine Learning Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Databearbetning och explorativ dataanalys”?

Ni läser in ett rådataset, analyserar fördelningar och korrelationer, identifierar problem med datakvaliteten och dokumenterar resultaten i en reproducerbar Jupyter-anteckningsbok. Ni övar på Machine Learning Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Machine Learning Academy?

Du behöver inga förkunskaper. Utbildningen i Machine Learning Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.

Hur lång tid tar lektionen ”Databearbetning och explorativ dataanalys”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Machine Learning Academy-lektionen?

Ja. Varje Machine Learning Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Projektavgränsning: definiera problemet och framgångskriterierna
  2. Databearbetning och explorativ dataanalys
  3. Turnering i modellval: jämför fem algoritmer
  4. Paketering, dokumentation och presentation av den slutliga modellen
← Tillbaka till Machine Learning Academy