Machine Learning Academy · Lezione

Data wrangling e analisi esplorativa dei dati

Caricherà un dataset grezzo, analizzerà distribuzioni e correlazioni, individuerà i problemi di qualità dei dati e documenterà i risultati in un notebook Jupyter riproducibile.

Lezione 2 di 413 passaggi

Data wrangling e analisi esplorativa dei dati è una lezione Machine Learning Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Machine Learning Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Machine Learning Academy include 4 lezioni in totale.

Che cos'è l'analisi esplorativa dei dati?

La Exploratory Data Analysis (EDA) è l'attività di analisi di un dataset prima della modellazione, per comprenderne struttura, distribuzioni, relazioni e problemi di qualità. Il termine è stato coniato da John Tukey e l'EDA segue un principio semplice: lasciar parlare i dati. Saltare l'EDA e passare direttamente alla modellazione è il secondo motivo più comune per cui i progetti di ML falliscono, dopo una definizione inadeguata del problema. L'EDA evita di costruire modelli su fondamenta difettose.

Caricamento e prima ispezione

Inizi sempre con un'ispezione strutturale: quante righe e colonne ci sono e quali sono i tipi di dati? Utilizzi df.shape, df.dtypes, df.head() e df.info(). Cerchi le colonne che sembrano numeriche ma sono memorizzate come object (stringhe) e quelle che sembrano categoriche ma sono codificate come interi. Tipi di dati non coerenti causano bug silenziosi nelle fasi successive, quando scikit-learn tratta una categoria codificata come intero alla stregua di una variabile continua.

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

Analisi univariata: distribuzioni

L'analisi univariata esamina una variabile alla volta. Per le feature numeriche, tracci istogrammi e calcoli le statistiche riassuntive (media, mediana, deviazione standard, asimmetria). Le distribuzioni fortemente asimmetriche (asimmetria > 2) spesso traggono vantaggio da una trasformazione logaritmica prima della modellazione. Per le feature categoriche, tracci grafici a barre delle frequenze dei valori. Le categorie presenti in meno dell'1% delle righe possono causare problemi con la codifica one-hot e la suddivisione stratificata.

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)

Tabella delle statistiche riassuntive

df.describe() produce conteggio, media, deviazione standard, minimo, quartili e massimo per ogni colonna numerica. La esamini con attenzione: un valore massimo di diversi ordini di grandezza superiore al 99° percentile segnala la presenza di valori anomali. Un minimo pari a zero nella colonna «giorni dall'ultimo acquisto» può significare che il cliente ha effettuato un acquisto oggi, oppure può essere un valore sentinella che indica dati mancanti. Comprendere questi casi limite previene errori silenziosi nelle fasi successive di preprocessing.

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

Analisi dei valori mancanti

I valori mancanti devono essere analizzati prima di prendere decisioni sull'imputazione. Calcoli la percentuale di valori nulli per colonna con df.isnull().mean(). Potrebbe essere necessario eliminare completamente le colonne con più del 50% di valori mancanti. Comprenda il meccanismo alla base dei valori mancanti: si tratta di valori mancanti completamente a caso (MCAR) oppure di valori mancanti non a caso (MNAR), ad esempio perché i clienti che hanno effettuato churn hanno eliminato le informazioni del proprio account? I valori mancanti MNAR sono di per sé informativi e dovrebbero essere codificati come indicatore binario.

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)

Analisi bivariata: correlazioni

L'analisi bivariata esamina le relazioni tra coppie di variabili. Per le relazioni tra variabili numeriche, calcoli una matrice di correlazione e la visualizzi come heat map con seaborn.heatmap. Correlazioni superiori a 0.95 tra due feature segnalano multicollinearità: entrambe contengono informazioni quasi identiche, quindi è possibile eliminarne una senza perdere capacità predittiva. Calcoli inoltre le correlazioni punto-biseriali tra le feature numeriche e l'obiettivo binario, per individuare in anticipo le feature più predittive.

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

Analisi della variabile obiettivo

Analizzi sempre separatamente la variabile obiettivo. Per la classificazione binaria, calcoli il tasso della classe positiva (df['churned'].mean()). Tassi inferiori al 5% o superiori al 95% indicano un grave sbilanciamento, che influisce sulla scelta dell'algoritmo e sulle metriche di valutazione. Per gli obiettivi di regressione, verifichi la normalità: gli obiettivi asimmetrici spesso traggono vantaggio da una trasformazione logaritmica prima dell'addestramento, soprattutto per i modelli basati su alberi, che ne sono immuni, ma in modo cruciale per la regressione lineare.

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)

Rilevamento e trattamento dei valori anomali

I valori anomali possono distorcere l'addestramento del modello, soprattutto nei modelli basati sulla distanza (KNN, SVM) e nella regressione lineare. Utilizzi il metodo IQR (segnalando i valori esterni all'intervallo [Q1 - 1.5·IQR, Q3 + 1.5·IQR]) oppure lo z-score (segnalando i valori con |z| > 3) per un rilevamento iniziale. Per ogni valore anomalo segnalato, verifichi se si tratta di un errore di inserimento, di un valore estremo legittimo o di un malfunzionamento del sensore. I valori estremi legittimi devono essere conservati; gli errori devono essere corretti o rimossi.

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

Grafici della relazione tra feature e obiettivo

Per le attività di classificazione, visualizzi come la distribuzione di ciascuna feature numerica differisce tra le classi utilizzando un violin plot o un box plot raggruppato in base all'obiettivo. Le feature le cui distribuzioni separano nettamente le due classi sono probabilmente predittive. Per le feature categoriche, un grafico a barre raggruppate del tasso di churn per valore della categoria mostra rapidamente quali categorie sono associate a un rischio maggiore.

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)

Documentazione dei risultati dell'EDA

I risultati dell'EDA devono essere documentati in un Jupyter notebook riproducibile e condiviso con il team. Come minimo, documenti: le colonne eliminate e il motivo, le decisioni di imputazione per ogni colonna, il trattamento dei valori anomali, l'entità dello sbilanciamento tra le classi, le feature più predittive e gli eventuali problemi di qualità dei dati sottoposti al team di data engineering. Questo notebook diventerà la sezione relativa alla qualità dei dati della futura model card e sarà prezioso per il debugging delle regressioni in produzione anche a distanza di mesi.

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

Strumenti per l'EDA automatizzata

Per dataset di grandi dimensioni con centinaia di feature, l'EDA manuale non è praticabile. ydata-profiling (in precedenza pandas-profiling) genera con una sola chiamata di funzione un report HTML interattivo con distribuzioni, correlazioni, valori mancanti e avvisi sui valori anomali per ogni colonna. sweetviz produce report comparativi tra suddivisioni train/test o segmenti della classe obiettivo. Utilizzi questi strumenti come punto di partenza, ma completi sempre l'analisi con grafici personalizzati specifici del dominio per le feature più importanti.

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

Verifica rapida

Verifichi la comprensione dei concetti di Machine Learning con Python presentati in questa lezione.

Riepilogo della lezione

In questa lezione ha imparato che: l'EDA analizza distribuzioni, relazioni, valori mancanti e valori anomali prima di qualsiasi modellazione, l'analisi bivariata (correlazioni, grafici delle relazioni tra feature e obiettivo) individua le feature più predittive e i risultati dell'EDA devono essere documentati in un notebook riproducibile per guidare le decisioni di preprocessing e fungere da registro della qualità dei dati. Ora avvieremo un confronto tra modelli per comparare cinque algoritmi sullo stesso dataset elaborato.

Gratis per iniziare

Impara Python con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
30
Lezioni
120

Domande Frequenti

La lezione «Data wrangling e analisi esplorativa dei dati» è gratuita?

Sì — il testo completo di «Data wrangling e analisi esplorativa dei dati» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Machine Learning Academy, passa a CoddyKit PRO. Il corso Machine Learning Academy include 4 lezioni in totale.

Cosa imparerò in «Data wrangling e analisi esplorativa dei dati»?

Caricherà un dataset grezzo, analizzerà distribuzioni e correlazioni, individuerà i problemi di qualità dei dati e documenterà i risultati in un notebook Jupyter riproducibile. Eserciti Machine Learning Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Machine Learning Academy?

Non è richiesta alcuna esperienza precedente. Machine Learning Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Data wrangling e analisi esplorativa dei dati»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Machine Learning Academy?

Sì. Ogni lezione Machine Learning Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Definizione dell'ambito del progetto: problema e criteri di successo
  2. Data wrangling e analisi esplorativa dei dati
  3. Torneo di selezione dei modelli: confronto tra cinque algoritmi
  4. Packaging, documentazione e presentazione del modello finale
← Torna a Machine Learning Academy