Pandas & NumPy Academy · Lezione

Pulizia dei dati e feature engineering

Applichi la checklist avanzata di pulizia, crei feature relative alle date e colonne con rapporti, quindi convalidi il dataset ripulito con asserzioni.

Lezione 2 di 413 passaggi

Pulizia dei dati e feature engineering è una lezione Pandas & NumPy 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 Pandas & NumPy Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Pandas & NumPy Academy include 4 lezioni in totale.

Caricamento del dataset sottoposto ad audit

Proseguendo con il progetto capstone, carichi il checkpoint Parquet pulito salvato nel passaggio precedente. In questo modo la fase di pulizia viene separata dall’acquisizione: può iterare sulla logica di pulizia senza eseguire nuovamente le lente operazioni di unione e parsing. Legga il Parquet clean_orders e verifichi che il numero di righe e i dtype corrispondano alle aspettative indicate nel riepilogo di audit. Il file Parquet conserva tutti i dtype, comprese le colonne categoriali, quindi non è necessario riconvertire i tipi.

import pandas as pd

# Load from checkpoint
df = pd.read_parquet('output/clean_orders.parquet')
print(f'Loaded: {df.shape}')
print(df.dtypes)
print(f'Date range: {df["order_date"].min().date()} to {df["order_date"].max().date()}')

Applicazione della checklist avanzata di pulizia

Con il dataset unito caricato, applichi la checklist avanzata di pulizia: rimuova i duplicati esatti e parziali in order_id, limiti gli outlier in unit_price utilizzando i recinti basati sull’IQR, standardizzi i valori incoerenti di category (ad esempio, 'Electronics' rispetto a 'electronics' e 'ELECTRONIC') e verifichi che quantity × unit_price sia sempre positivo per gli ordini normali. Ogni passaggio è una funzione che accetta e restituisce un DataFrame, rendendo la pipeline testabile e reversibile.

import pandas as pd
import numpy as np

def remove_duplicates(df):
    n_before = len(df)
    df = df.drop_duplicates(subset=['order_id'], keep='first')
    print(f'Duplicates removed: {n_before - len(df)}')
    return df

def standardise_categories(df):
    df['category'] = (df['category']
                      .astype(str)
                      .str.strip()
                      .str.title())
    return df

def cap_price_outliers(df):
    q1, q3 = df['unit_price'].quantile([0.25, 0.75])
    iqr = q3 - q1
    upper = q3 + 3 * iqr
    df['unit_price'] = df['unit_price'].clip(upper=upper)
    return df

df = remove_duplicates(df)
df = standardise_categories(df)
df = cap_price_outliers(df)
print('Cleaning complete.')

Creazione delle feature temporali

Estragga le feature temporali dalla data dell’ordine utilizzando l’accessor .dt. Crei le colonne year, month, quarter, day_of_week e week_of_year. Queste feature alimentano le analisi con groupby (ad esempio, il fatturato mensile), i filtri basati sul tempo (solo il terzo trimestre) e le visualizzazioni. Crei inoltre una colonna stringa year_month (ad esempio, '2024-06') come etichetta del periodo leggibile per gli assi dei grafici.

import pandas as pd

df['year'] = df['order_date'].dt.year
df['month'] = df['order_date'].dt.month
df['quarter'] = df['order_date'].dt.quarter
df['day_of_week'] = df['order_date'].dt.dayofweek  # 0=Monday
df['week'] = df['order_date'].dt.isocalendar().week.astype('int32')
df['year_month'] = df['order_date'].dt.to_period('M').astype(str)

print('Date features created:')
print(df[['order_date', 'year', 'month', 'quarter', 'year_month']].head())

Calcolo del fatturato per riga d’ordine

La feature più fondamentale in un dataset di vendite è il fatturato per riga d’ordine: revenue = quantity × unit_price. La crei come nuova colonna. Se sono disponibili i dati sui costi, crei anche una colonna gross_margin: margin = (price - cost) / price. Queste colonne derivate sono gli elementi costitutivi di tutti i KPI relativi al fatturato. Utilizzi sempre operazioni vettorializzate sulle colonne invece dei cicli: una singola assegnazione sull’intera colonna è enormemente più veloce dell’iterazione riga per riga.

import pandas as pd

# Line-item revenue
df['revenue'] = (df['quantity'] * df['unit_price']).astype('float32')

# Gross margin (if unit_cost column exists)
if 'unit_cost' in df.columns:
    df['gross_margin'] = (df['unit_price'] - df['unit_cost']) / df['unit_price']

# Discount flag: orders with more than 20% off list price
if 'list_price' in df.columns:
    df['is_discounted'] = df['unit_price'] < df['list_price'] * 0.8

print('Revenue stats:')
print(df['revenue'].describe().round(2))

Assegnazione delle coorti dei clienti

Una coorte è un gruppo di clienti che condivide una caratteristica, in genere il periodo in cui ha effettuato il primo acquisto. Assegni ogni cliente alla relativa coorte di acquisizione individuando la data del primo ordine. Utilizzi groupby('customer_id')['order_date'].min() per calcolare la data del primo ordine per ciascun cliente, quindi crei una colonna cohort_month convertendo tale data in un periodo anno-mese. Questa etichetta della coorte è la base della matrice di retention nella lezione successiva.

import pandas as pd

# First purchase date per customer
first_purchase = (
    df.groupby('customer_id')['order_date']
    .min()
    .dt.to_period('M')
    .astype(str)
    .rename('cohort_month')
)

# Merge back onto orders
df = df.merge(first_purchase, on='customer_id', how='left')
print('Cohort distribution (top 5):')
print(df['cohort_month'].value_counts().head())
print(f'Distinct cohorts: {df["cohort_month"].nunique()}')

Feature del valore del ciclo di vita del cliente

Calcoli le feature riepilogative a livello di cliente: numero totale di ordini, fatturato totale, valore medio dell’ordine, giorni trascorsi dal primo e dall’ultimo acquisto e numero di categorie distinte acquistate. Esegua il merge di queste informazioni nel DataFrame principale come colonne di arricchimento a livello di cliente. Queste feature vengono utilizzate per la segmentazione (ad esempio, clienti di alto o basso valore) e come input per i modelli di machine learning che prevedono il churn o la probabilità di upselling.

import pandas as pd

customer_stats = df.groupby('customer_id').agg(
    total_orders=('order_id', 'nunique'),
    total_revenue=('revenue', 'sum'),
    avg_order_value=('revenue', 'mean'),
    categories_purchased=('category', 'nunique'),
    first_order=('order_date', 'min'),
    last_order=('order_date', 'max')
).reset_index()

customer_stats['days_as_customer'] = (
    (customer_stats['last_order'] - customer_stats['first_order'])
    .dt.days
)

print(customer_stats.describe().round(2))

Validazione dello schema con asserzioni

Dopo aver creato le feature, esegua le asserzioni di validazione dello schema per confermare che i dati soddisfino le aspettative prima di passarli alla fase di analisi. Verifichi che tutte le colonne previste esistano, che il fatturato sia non negativo per gli ordini normali, che cohort_month non sia nullo e che year_month corrisponda all’anno dell’analisi. Queste asserzioni agiscono come un contratto: se una di esse fallisce, la pipeline si interrompe immediatamente con un messaggio di errore chiaro, invece di produrre silenziosamente risultati errati.

import pandas as pd

def validate_clean_df(df):
    required_cols = ['order_id', 'customer_id', 'revenue', 'year_month',
                     'cohort_month', 'category', 'region', 'order_date']
    missing = [c for c in required_cols if c not in df.columns]
    assert not missing, f'Missing columns: {missing}'

    assert (df['revenue'] >= 0).all(), 'Negative revenue found'
    assert df['cohort_month'].notna().all(), 'Null cohort_month values'
    assert df['order_date'].notna().all(), 'Null order dates'
    print(f'Validation passed: {len(df):,} rows, {len(df.columns)} columns')

validate_clean_df(df)

Gestione delle categorie a bassa frequenza

Nei dataset reali, alcune categorie o regioni compaiono solo poche volte, un numero insufficiente per un’analisi significativa. Sostituisca i valori a bassa frequenza con 'Other' per evitare grafici sovraffollati da decine di categorie presenti in un solo ordine. Una soglia pratica è accorpare i valori che compaiono in meno dello 0,5% delle righe. Questo è importante anche per il machine learning: applicare l’one-hot encoding a 200 categorie rare spreca memoria e aggiunge rumore.

import pandas as pd

def collapse_rare_values(df, col, min_pct=0.005):
    threshold = len(df) * min_pct
    counts = df[col].value_counts()
    rare = counts[counts < threshold].index
    n_rare = len(rare)
    df[col] = df[col].apply(lambda x: 'Other' if x in rare else x)
    print(f'{col}: collapsed {n_rare} rare values into "Other"')
    return df

df = collapse_rare_values(df, 'category', min_pct=0.005)
df = collapse_rare_values(df, 'region', min_pct=0.005)
print('Category distribution after collapsing:')
print(df['category'].value_counts())

Salvataggio del dataset con feature ingegnerizzate

Salvi il DataFrame completamente pulito e con le feature ingegnerizzate come checkpoint Parquet. Questo è il dataset pronto per l’analisi, ovvero il risultato di tutti i passaggi di acquisizione, pulizia e creazione delle feature. Le fasi successive della pipeline (calcolo dei KPI, visualizzazione e reporting) leggeranno da questo checkpoint. Il checkpoint funge anche da deliverable: può essere condiviso con i membri del team o caricato in un data lake, affinché altri possano interrogarlo con SQL o Pandas.

import pandas as pd

# Convert category columns back to Categorical for memory efficiency
for col in ['category', 'region', 'acquisition_channel']:
    if col in df.columns:
        df[col] = df[col].astype('category')

# Save analysis-ready dataset
df.to_parquet('output/analysis_ready.parquet', index=False)

# Also save customer stats for segmentation
customer_stats.to_parquet('output/customer_stats.parquet', index=False)

print(f'Analysis-ready dataset: {df.shape}')
print(f'Memory usage: {df.memory_usage(deep=True).sum()/1e6:.1f} MB')

Riepilogo della creazione delle feature

Una buona creazione delle feature bilancia l’aggiunta di segnali predittivi con la necessità di mantenere la pipeline interpretabile e testabile. Le feature create in questa fase — fatturato, componenti della data, cohort_month, statistiche sui clienti e categorie accorpate — sono state tutte determinate dagli obiettivi dell’analisi definiti nella configurazione del progetto. Resista alla tentazione di creare decine di feature in modo speculativo. Per ogni feature si chieda: verrà utilizzata in almeno un KPI o in una visualizzazione? In caso contrario, rimandi la sua creazione. Mantenga il dataset pronto per l’analisi snello e mirato.

import pandas as pd

# Summary of engineered features
df = pd.read_parquet('output/analysis_ready.parquet')

original_cols = ['order_id', 'customer_id', 'order_date', 'quantity', 'unit_price']
engineered_cols = [c for c in df.columns if c not in original_cols]

print('Original columns:', original_cols)
print('Engineered features:', engineered_cols)
print(f'Total columns: {len(df.columns)}')
print(f'Total rows: {len(df):,}')

Documentazione delle decisioni nel codice

Per ogni decisione di pulizia o di creazione delle feature non immediatamente evidente, aggiunga un commento che ne spieghi il motivo. In futuro, Lei o un membro del team potreste non ricordare perché avete impostato il moltiplicatore IQR su 3 invece che su 1,5, o perché avete utilizzato lo 0,5% come soglia per le categorie rare. I commenti inline e un registro delle decisioni (un semplice elenco nel README del progetto o in un file Markdown) rendono la pipeline manutenibile e verificabile. Il vero deliverable è un codice pulito e documentato: i file di output ne sono solo la conseguenza.

# Engineering decisions log
DECISIONS = '''
# Data Cleaning & Feature Engineering Decisions

## Duplicate handling
Kept first occurrence of duplicate order_id (most likely the original order).

## Outlier capping
Unit price capped at Q3 + 3*IQR (not 1.5*IQR) because price distribution
has legitimate high-value enterprise orders that should not be removed.

## Rare category threshold: 0.5%
Values below 0.5% of total orders collapsed to "Other" to keep charts readable
and avoid spurious significance in category-level tests.

## Cohort assignment
Cohort = first purchase calendar month (not signup month), because many users
sign up but do not purchase until months later.
'''
print(DECISIONS)

Verifica rapida

Verifichi la Sua comprensione dei concetti di analisi dei dati trattati in questa lezione.

Riepilogo della lezione

In questa lezione ha imparato che: le funzioni modulari di pulizia (rimozione dei duplicati, limitazione degli outlier e standardizzazione delle categorie) accettano e restituiscono ciascuna un DataFrame per facilitare i test, la creazione delle feature ha prodotto componenti della data, fatturato per riga d’ordine, coorti dei clienti e statistiche riepilogative, mentre le asserzioni di validazione dello schema proteggono il passaggio dalla pulizia all’analisi. Ora calcoleremo i KPI principali del progetto: retention mensile delle coorti, fatturato dei prodotti e utenti attivi mobili.

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 «Pulizia dei dati e feature engineering» è gratuita?

Sì — il testo completo di «Pulizia dei dati e feature engineering» è 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 Pandas & NumPy Academy, passa a CoddyKit PRO. Il corso Pandas & NumPy Academy include 4 lezioni in totale.

Cosa imparerò in «Pulizia dei dati e feature engineering»?

Applichi la checklist avanzata di pulizia, crei feature relative alle date e colonne con rapporti, quindi convalidi il dataset ripulito con asserzioni. Eserciti Pandas & NumPy 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 Pandas & NumPy Academy?

Non è richiesta alcuna esperienza precedente. Pandas & NumPy 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 «Pulizia dei dati e feature engineering»?

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 Pandas & NumPy Academy?

Sì. Ogni lezione Pandas & NumPy 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. Configurazione del progetto e acquisizione dei dati
  2. Pulizia dei dati e feature engineering
  3. Analisi e calcolo dei KPI
  4. Visualizzazione finale ed esportazione del report
← Torna a Pandas & NumPy Academy