Vai al contenuto principale
Data cleaning, data quality e feature engineering - immagine header GinnyTech con visual cosmico editoriale

Data cleaning, data quality e feature engineering

Data cleaning, data quality e feature engineering su GinnyTech: decidere quali trasformazioni automatizzare e quali richiedono owner di dominio con controlli, ownership e output revisionabili.

AD
Creato daAndrii Dyshkantiuk
Lezione 221 / 236Livello: AvanzatoDurata: 30 minPrerequisiti: 1

Cosa imparerai

  • Progettare workflow AI per dati con controlli, owner e output revisionabili
  • Applicare AI, AutoML o agentic AI a casi business analytics senza perdere rigore
  • Riconoscere rischi di leakage, drift, costo, privacy e automazione non governata

Data cleaning, data quality e feature engineering

Siamo nel binario dei sistemi LLM, quello in cui gli assistenti generativi e l’AutoML toccano i dati da vicino. Partiamo da una scena frequente: un modello di churn che in validazione sembra ottimo e in produzione non distingue un cliente fedele da uno perso non ha un problema di algoritmo. Ha quasi sempre un problema a monte: una feature che sbirciava il futuro, una definizione di target cambiata senza avvisare nessuno, una colonna di date parseata in due fusi diversi. Chi lavora con i dati impara presto che la parte gloriosa — scegliere il modello, ottimizzare gli iperparametri — pesa poco rispetto a quella paziente: capire cosa contengono davvero le tabelle, decidere quali trasformazioni sono legittime e costruire controlli che reggano quando i dati cambiano. L’AI generativa e l’AutoML possono accelerare ognuno di questi passaggi, ma solo se il confine tra ciò che si automatizza e ciò che richiede un owner di dominio resta esplicito.

Il perimetro di questa lezione

Questa lezione decide quali trasformazioni sui dati può proporre l’AI e quali restano dell’esperto di dominio, con il vincolo che ogni statistica si calcola sul solo training e ogni colonna supera il test del momento di disponibilità.

La sequenza operativa

Ecco come si lavora, nell’ordine giusto.

  1. Profila ogni colonna su tipi, mancanti, cardinalità e distribuzioni prima di correggere un solo valore.
  2. Classifica ogni anomalia con il proprietario del dato: errore di misura, vuoto strutturale o segnale raro da preservare.
  3. Gestisci i mancanti per meccanismo: cancellazione solo se casuali, imputazione con covariate se legati a variabili osservate, indicatore dedicato se il vuoto porta segnale.
  4. Incapsula ogni statistica di imputazione, codifica e normalizzazione in una pipeline stimata sul solo training.
  5. Etichetta ogni feature con il momento di disponibilità e scarta quelle incalcolabili al momento della predizione.
  6. Traduci i controlli in test automatici con matrice blocca-avvisa e proprietario di risposta.

Quando i dati sporchi costano più del modello

C’è un malinteso persistente: che il guadagno stia nello scegliere un booster invece della regressione logistica, o nel provare l’ennesimo modello alla moda. Nella pratica dei progetti tabulari, la differenza tra un modello mediocre e uno utile arriva dal lavoro sui dati. Una colonna importo con una quota di zeri che in realtà sono mancanti non registrati, un join che duplica le righe degli utenti con più abbonamenti, una variabile di recency calcolata alla data di estrazione invece che alla data di scoring: ognuno di questi difetti sposta le metriche più di qualsiasi tuning.

Il punto economico è diretto. Un errore di pulizia scoperto dopo il deploy costa gli sforzi di retraining, la sfiducia degli stakeholder e, nei casi peggiori, decisioni operative sbagliate — sconti offerti ai clienti sbagliati, frodi non intercettate, magazzino ordinato sulle previsioni di un modello contaminato. Il data cleaning non è igiene preliminare da sbrigare in fretta: è la parte del progetto dove si decide cosa il modello potrà imparare.

Una distinzione utile separa tre attività che spesso vengono confuse. Il data cleaning corregge i difetti osservabili del dataset — mancanti, duplicati, formati incoerenti, outlier da errore di misura. La data quality è il sistema di garanzie che impedisce ai difetti di rientrare: test automatici, contratti sulle tabelle, monitoraggio nel tempo. Il feature engineering trasforma le colonne grezze in segnali che il modello può usare — aggregazioni temporali, encoding di categoriche, interazioni. Pulizia senza quality è fatica che si ripete ogni mese; feature senza pulizia sono decorazioni su fondamenta instabili.

AttivitàDomanda guidaOutput tipico
Data cleaningCosa c’è di sbagliato in questi dati?Dataset corretto e documentato
Data qualityCome impedisco che si rompa di nuovo?Test, soglie, alert
Feature engineeringQuale segnale aiuta il modello?Colonne derivate versionate

Profilare prima di pulire: il contratto con i dati grezzi

La tentazione è aprire il notebook e iniziare a riempire i null. Resistere a questa tentazione è la prima competenza. Prima di toccare un valore, serve un profilo sistematico del dataset: per ogni colonna, tipo effettivo contro tipo dichiarato, tasso di mancanti, cardinalità, distribuzione, valori anomali evidenti. Strumenti come pandas-profiling o una query SQL di conteggi danno in minuti una mappa che orienta tutto il resto.

# Profilo rapido di un dataframe: tipi, mancanti, cardinalità
# Ogni colonna viene descritta prima di decidere qualsiasi correzione
profilo = df.describe(include="all").T
profilo["mancanti_pct"] = df.isna().mean().mul(100).round(1)
profilo["unici"] = df.nunique()
# Le colonne con più del 40-50% di mancanti meritano
# una discussione con il dominio prima di qualsiasi imputazione
sospette = profilo[profilo["mancanti_pct"] > 40]

Il profilo va letto con il dominio, non da solo. Una colonna data_chiusura_ticket vuota nel 70% delle righe non è un problema di qualità se i ticket aperti non hanno data di chiusura: il mancante è strutturale e porta informazione. La stessa percentuale su codice_fiscale è un disastro di ingestion. Solo chi conosce il processo che genera i dati distingue i due casi, ed è qui che l’AI può aiutare come assistente — suggerendo interpretazioni candidate e domande da porre al proprietario del dato — ma mai come giudice finale.

Da questo lavoro nasce un artefatto sottovalutato: il dizionario dati vivente. Non la documentazione scritta una volta e mai aggiornata, ma una tabella che per ogni campo registra significato, sorgente, grain, regola di qualità attesa e owner. Quando mesi dopo una pipeline cambia formato e rompe una feature, il dizionario dice chi chiamare e cosa controllare. L’AI può generare la prima bozza del dizionario dal profilo statistico e dagli schemi, e l’umano la corregge: un buon esempio di divisione dei compiti.

Valori mancanti: capire il meccanismo prima di riempire

Non tutti i null sono uguali. Il modo in cui si riempiono decide se il modello impara qualcosa di vero o un artefatto. La statistica classica distingue tre meccanismi, con conseguenze operative immediate. Se i dati mancano completamente a caso — per esempio un crash del logger che perde righe indipendentemente dal contenuto — cancellare le righe incomplete introduce poco bias, oltre alla perdita di potenza statistica. Se la mancanza dipende da variabili osservate — il campo reddito è vuoto più spesso per i giovani, ma condizionatamente all’età la mancanza è casuale — serve un’imputazione che tenga conto delle covariate. Se dipende dal valore stesso non osservato — chi ha il reddito più alto omette di dichiararlo — nessuna imputazione standard è corretta senza modellare il meccanismo di selezione. In quest’ultimo caso la scelta onesta è spesso tenere un indicatore di mancanza come feature.

# Strategia differenziata per i mancanti: mediana per le numeriche
# robuste, categoria esplicita per le categoriche, flag di mancanza
# La colonna _mancante conserva il segnale del meccanismo MNAR
for col in numeriche:
    df[col + "_mancante"] = df[col].isna().astype(int)
    df[col] = df[col].fillna(df[col].median())
for col in categoriche:
    df[col] = df[col].fillna("Sconosciuto")

Il test pratico è semplice: confrontate la distribuzione del target tra righe con e senza mancanti su una colonna chiave. Se i clienti senza reddito hanno un tasso di churn doppio rispetto agli altri, il mancante porta segnale e cancellarlo o imputarlo con la media distrugge informazione. Il flag binario di mancanza, aggiunto come feature a parte, cattura spesso più potere predittivo dell’imputazione stessa.

L’errore grave è l’imputazione calcolata sull’intero dataset prima dello split train/test: media, mediana o moda stimate anche sul test contaminano il training con informazioni future. La regola è meccanica — ogni statistica di imputazione si calcola sul solo train e si applica al test — ma va resa strutturale con una pipeline (sklearn.pipeline.Pipeline o equivalente) invece che affidata alla disciplina del singolo notebook. L’AI che genera codice di preprocessing va istruita esplicitamente su questo vincolo: chiedetele una pipeline, non una sequenza di assegnazioni sul dataframe globale.

Duplicati, outlier e inconsistenze: prima le regole, poi i modelli

I duplicati sembrano banali finché non se ne incontra uno che non lo è. Due righe identiche su tutte le colonne sono quasi sempre un errore di ingestion e si deduplicano senza rimpianti. Due righe con stesso user_id e timestamp diverso possono essere eventi legittimi — un utente che ordina due volte — oppure il sintomo di un join a ventaglio che ha moltiplicato le righe. La verifica passa dal grain dichiarato della tabella: se la tabella dichiara una riga per utente al giorno e trovate tre righe per lo stesso utente-giorno, il join è rotto, non i dati. Il controllo si scrive in SQL prima ancora che in Python:

-- Verifica del grain: ogni combinazione utente-giorno deve apparire una volta sola
-- Le righe restituite sono violazioni da investigare, non da cancellare alla cieca
SELECT user_id, data_evento, COUNT(*) AS righe
FROM eventi
GROUP BY user_id, data_evento
HAVING COUNT(*) > 1;

Gli outlier richiedono la stessa prudenza. La regola meccanica — tutto oltre tre deviazioni standard è sospetto — tratta allo stesso modo un errore di battitura (età 250 anni) e un evento reale ma raro (un acquisto aziendale enorme in un dataset di scontrini retail). Il primo va corretto o rimosso, il secondo è spesso il segnale più prezioso del dataset, soprattutto in frodi e churn. Il criterio operativo: un outlier è errore solo se viola un vincolo di dominio verificabile — età negativa, data futura su un evento passato, percentuale oltre 100. Altrimenti si gestisce con trasformazioni robuste (log, winsorizzazione, modelli insensibili come i tree-based) invece che con la cancellazione.

Le inconsistenze tra colonne sono la categoria più insidiosa perché nessun controllo univariato le intercetta: data_fine precedente a data_inizio, stato_ordine = "spedito" con data_spedizione nulla, CAP che non appartiene alla provincia dichiarata. Qui le regole di validazione incrociata — scritte come asserzioni esplicite — valgono più di qualsiasi modello di anomaly detection. L’AI è utile per generarle: datole lo schema e qualche riga di esempio, produce una bozza di checklist di coerenza che il dominio poi valida. Ma la decisione su cosa blocca la pipeline e cosa genera solo un warning resta umana, perché dipende dal costo dei falsi positivi sul processo a valle.

Feature engineering: tradurre il dominio in colonne

Se la pulizia rimuove il falso, il feature engineering aggiunge il vero: trasforma colonne grezze in rappresentazioni che il modello può sfruttare. La materia prima non è la creatività matematica ma la conoscenza del processo. In un problema di churn telecom, sapere che il call center registra un codice reclamo significa poter costruire numero_reclami_90gg — una feature che regolarmente batte dozzine di combinazioni polinomiali generate alla cieca. La domanda da porsi per ogni candidata è sempre la stessa: quale comportamento del mondo reale dovrebbe catturare questa colonna, e perché il modello non può ricavarlo da solo dalle colonne esistenti?

Le famiglie di trasformazioni ricorrenti sono poche e vale la pena conoscerle a memoria. Le aggregazioni temporali — conteggi, somme, medie su finestre mobili — convertono log di eventi in segnali per utente: spesa media degli ultimi 30 giorni, numero di login notturni, distanza dall’ultimo acquisto (recency). Le differenze e i rapporti catturano dinamiche: variazione della spesa rispetto al trimestre precedente, rapporto tra ticket aperti e chiusi. Le feature di calendario — giorno della settimana, festività, distanza da un evento noto — servono quando il fenomeno ha stagionalità. Le interazioni tra variabili — canale di acquisizione per fascia di prezzo — catturano effetti che i modelli lineari non vedono da soli, mentre i modelli ad albero le approssimano ma con più dati.

# Feature temporali da un log eventi: aggregate su finestra mobile
# La finestra si ancora alla data di osservazione, mai a eventi futuri
recenti = eventi[eventi["data"] >= data_osservazione - pd.Timedelta(days=90)]
agg = recenti.groupby("user_id").agg(
    n_eventi_90gg=("evento_id", "count"),   # intensità d'uso recente
    spesa_90gg=("importo", "sum"),           # valore generato di recente
    recency_gg=("data", lambda s: (data_osservazione - s.max()).days),
)

Il vincolo che attraversa tutte queste costruzioni è il punto temporale di osservazione: ogni feature deve essere calcolabile con le sole informazioni disponibili al momento in cui il modello verrà usato. Una feature giorni_tra_ordine_e_reso è legittima per analizzare i resi a posteriori, ma è leakage se il modello deve decidere prima che il reso avvenga. Il test mentale — “saprei calcolare questo valore il giorno dello scoring?” — intercetta la maggior parte delle contaminazioni prima che diventino metriche illusorie.

Codifiche e scaling: dettagli che spostano le metriche

Le variabili categoriche vanno convertite in numeri, e la scelta della codifica interagisce con il modello in modi che conviene capire una volta per tutte. L’one-hot encoding è trasparente e funziona bene fino a qualche decina di categorie; oltre — CAP, SKU, user agent — esplode la dimensionalità e conviene il target encoding (media del target per categoria) o gli embedding appresi. Il prezzo del target encoding è il leakage interno: se la media per categoria è calcolata sulle stesse righe su cui si allena, il modello impara a memoria. La correzione standard è il calcolo out-of-fold — le medie per un fold si stimano sugli altri fold — più uno smoothing che tira le categorie rare verso la media globale. Con peso alto, le categorie con poche osservazioni collassano verso la media invece di produrre stime rumorose che il modello prende per oro colato.

Lo scaling — standardizzazione o normalizzazione min-max — è obbligatorio per modelli sensibili alle distanze e ai gradienti (k-NN, SVM, reti neurali, regressione regolarizzata) e superfluo per gli alberi e le loro ensemble, che decidono su soglie. L’errore non è dimenticarlo dove serve, ma applicarlo dove non serve aggiungendo complessità: ogni trasformazione è un passaggio in più da mantenere in produzione e da spiegare quando qualcosa si rompe. Anche qui media e deviazione standard si stimano sul solo train, dentro la pipeline, mai sull’intero dataset.

Data quality in produzione: test che bloccano e metriche che avvisano

Un dataset pulito una volta si sporca di nuovo al primo cambio di schema, al primo deploy della app che logga in un formato diverso, alla prima migrazione del gestionale. La data quality è la risposta ingegneristica a questa entropia: un insieme di controlli eseguiti a ogni run della pipeline, con esiti che bloccano o avvisano. Il framework mentale più diffuso organizza i controlli in dimensioni — completezza (mancanti sotto soglia), unicità (niente duplicati sulle chiavi), validità (formati e range rispettati), coerenza (regole incrociate verificate), tempestività (dati arrivati entro la SLA) — e per ognuna definisce soglia ed azione.

# Test di qualità eseguibili a ogni run: soglie esplicite, esito booleano
# Un fallimento su chiave primaria blocca; uno sui mancanti avvisa
def test_qualita(df):
    assert df["user_id"].is_unique, "Chiave primaria duplicata: pipeline bloccata"
    assert df["user_id"].isna().mean() < 0.01, "Troppi id mancanti"
    assert (df["importo"] >= 0).all(), "Importi negativi non ammessi"
    assert df["data_evento"].max() >= ieri, "Dati non aggiornati: verificare ingestion"

Strumenti come Great Expectations, Soda o i più leggeri dbt tests portano questi controlli dentro la pipeline con report leggibili e storico degli esiti. La distinzione operativa è tra controlli bloccanti — chiave duplicata, schema incompatibile, volume crollato — che fermano tutto perché il danno di procedere supera il costo del fermo, e controlli di avviso — deriva lieve di una distribuzione, colonna nuova mai vista — che aprono un ticket senza fermare il flusso. Definire questa matrice prima dell’incidente, con owner e tempi di risposta, è ciò che separa un team che scopre i problemi dai dashboard degli utenti da uno che li trova nei log della pipeline.

Il monitoraggio delle feature in produzione merita un discorso a parte perché intercetta il degrado silenzioso: il modello continua a rispondere, ma i dati in input sono cambiati. La tecnica standard confronta la distribuzione corrente di ogni feature con quella del training — test di Kolmogorov-Smirnov per le numeriche, chi-quadro o PSI per le categoriche — e alza un alert oltre soglia. Un PSI sopra 0,25 su una feature importante significa che il mondo è cambiato abbastanza da rimettere in discussione il modello, e la risposta non è mai solo “riallenare”: prima si capisce se il cambiamento è un nuovo regime stabile, un errore di ingestion o un fenomeno stagionale noto.

Cosa delegare all’AI e cosa tenere sotto ownership umana

L’AI generativa accelera il lavoro sui dati in tre punti precisi. Genera codice boilerplate di profiling, pulizia e feature a partire dalla descrizione dello schema — con l’umano che verifica grain, leakage e statistiche calcolate sul train. Suggerisce feature candidate leggendo dizionario dati e letteratura di dominio, ampliando lo spazio delle ipotesi oltre l’esperienza del singolo analista. Scrive la documentazione — dizionari dati, data card, descrizioni delle trasformazioni — che i team rimandano sempre e che serve proprio quando le cose si rompono. L’AutoML copre un quarto punto: esplora sistematicamente combinazioni di preprocessing e modelli, stabilendo una baseline onesta contro cui misurare il lavoro manuale.

Quattro cose restano invece sotto ownership umana senza eccezioni. La definizione del target e del punto temporale di osservazione, perché un errore qui invalida tutto a valle e nessun benchmark lo intercetta. Le soglie dei controlli di qualità e la matrice blocca-avvisa, perché riflettono costi di business che il modello non conosce. La validazione delle feature dal punto di vista del dominio — quella colonna ha senso nel mondo reale o è un artefatto del join? E la decisione di fermare o ritirare un modello in produzione, che richiede responsabilità, non probabilità.

A salvare i progetti non è mai una tecnica esotica ma un controllo banale — verificare che ogni feature fosse calcolabile alla data di osservazione — eseguito perché il workflow lo prevedeva come passaggio obbligato. La maturità di un team dati non si misura dai modelli che addestra ma dai controlli che non salta mai, nemmeno quando le metriche in validazione sembrano già ottime.

Verdetto: l’AI genera codice di pulizia e candidate, il dominio firma target, soglie e fermo macchina; tutto il resto è rifinitura.

Il caso Mars Climate Orbiter

Nel 1999 la sonda Mars Climate Orbiter si disintegrò nell’atmosfera marziana dopo un viaggio da 125 milioni di dollari. La causa fu un’incoerenza tra dati mai validata: un fornitore lavorava in libbre-forza per secondo, il laboratorio NASA in newton per secondo. Nessun controllo incrociato bloccò il rilascio dei comandi di navigazione. È il caso estremo di ciò che insegna questa lezione: l’errore non era nel modello di volo ma nei dati in ingresso, e un test di coerenza da poche righe lo avrebbe intercettato.

Domande per chiudere la lezione

  1. Come distingui un mancante strutturale da un difetto di ingestion prima di imputarlo?
  2. Perché una statistica calcolata su tutto il dataset invalida la validazione e dove va confinata?
  3. Quale domanda rivela una feature che sbircia il futuro prima del primo training?
  4. Quali controlli bloccano la pipeline e quali aprono solo un ticket?
Serve una mano concreta?

Bloccato su questo argomento o vuoi applicarlo al tuo caso? Prenota una call di 15 minuti con un analista esperto.

Prenota una call