W3docs

Dati Categoriali

Impara a codificare i dati categoriali in Python con Label Encoding, Ordinal Encoding, One-Hot Encoding e pd.get_dummies con esempi scikit-learn.

I dati categoriali sono qualsiasi tipo di dato che assume un insieme limitato e fisso di valori — come "red", "blue", "green" per una colonna del colore, oppure "low", "medium", "high" per una valutazione di gravità. La maggior parte degli algoritmi di machine learning lavora con numeri, quindi le colonne categoriali devono essere convertite in una rappresentazione numerica prima dell'addestramento.

Questo capitolo illustra le principali strategie di codifica, quando scegliere ciascuna e come applicarle correttamente in Python usando pandas e scikit-learn senza far trapelare informazioni dal set di test nel modello.

Perché la Codifica è Importante

Fornire valori stringa grezzi a uno stimatore scikit-learn genera un ValueError. Anche quando una colonna contiene già numeri — come 1, 2, 3 che rappresentano "small", "medium", "large" — un algoritmo che tratta i valori delle feature come numeri continui inferirà una relazione falsa (ad es., "large" è tre volte "small"). La codifica permette di rappresentare accuratamente la vera relazione.

La scelta della codifica dipende da due domande:

  1. Esiste un ordine naturale? Il colore non ha un ordine naturale (nominale). La taglia di una maglietta ha un ordine naturale (ordinale). La codifica corretta preserva l'ordine quando esiste e lo ignora quando non esiste.
  2. Quanti valori distinti (cardinalità) ha la colonna? Le colonne ad alta cardinalità (centinaia di città uniche, ID prodotto) possono creare migliaia di colonne dummy con il One-Hot Encoding, penalizzando sia la memoria che le prestazioni del modello.

Impostare un Dataset di Esempio

Gli esempi seguenti utilizzano un piccolo dataset di abbigliamento così da poter seguire l'output con precisione.

import pandas as pd

data = {
    "color":  ["red", "green", "blue", "green", "red"],
    "size":   ["S", "M", "L", "S", "M"],
    "price":  [10, 20, 30, 10, 20],
    "in_stock": [True, True, False, True, False],
}

df = pd.DataFrame(data)
print(df)

Output:

   color size  price  in_stock
0    red    S     10      True
1  green    M     20      True
2   blue    L     30     False
3  green    S     10      True
4    red    M     20     False

Label Encoding

Il Label Encoding sostituisce ogni categoria con un intero. Il LabelEncoder di scikit-learn assegna gli interi in ordine alfabetico.

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
df["color_encoded"] = le.fit_transform(df["color"])

print(df[["color", "color_encoded"]])
print("Classes:", list(le.classes_))

Output:

   color  color_encoded
0    red              2
1  green              1
2   blue              0
3  green              1
4    red              2
Classes: ['blue', 'green', 'red']

blue → 0, green → 1, red → 2 (ordine alfabetico).

Quando usarlo: il Label Encoding è pensato per la variabile target (y), non per le feature di input. Applicato a una colonna di feature nominale, gli interi codificati implicano un ordinamento che non esiste, il che fuorvia i modelli basati su alberi ed è dannoso per i modelli lineari.

Invertire la codifica:

decoded = le.inverse_transform([0, 1, 2])
print(decoded)  # ['blue' 'green' 'red']

Ordinal Encoding

L'Ordinal Encoding è simile al Label Encoding ma consente di specificare l'ordine esatto delle categorie. Usalo per le feature in cui l'ordine è significativo.

from sklearn.preprocessing import OrdinalEncoder

# Define the order explicitly: S < M < L
oe = OrdinalEncoder(categories=[["S", "M", "L"]])
df["size_encoded"] = oe.fit_transform(df[["size"]])

print(df[["size", "size_encoded"]])

Output:

  size  size_encoded
0    S           0.0
1    M           1.0
2    L           2.0
3    S           0.0
4    M           1.0

Il modello può ora inferire correttamente che L (2) > M (1) > S (0).

Gestione delle categorie sconosciute al momento della predizione:

# Use handle_unknown='use_encoded_value' with unknown_value=-1
oe_safe = OrdinalEncoder(
    categories=[["S", "M", "L"]],
    handle_unknown="use_encoded_value",
    unknown_value=-1,
)
oe_safe.fit(df[["size"]])
print(oe_safe.transform([["XL"]]))  # [[-1.]]

One-Hot Encoding

Il One-Hot Encoding crea una colonna binaria per ogni categoria. Un 1 in una colonna indica che la riga appartiene a quella categoria; tutte le altre colonne sono 0. Questa è la scelta standard per le feature nominali (non ordinate) fornite a modelli lineari, SVM e reti neurali.

from sklearn.preprocessing import OneHotEncoder
import numpy as np

ohe = OneHotEncoder(sparse_output=False, handle_unknown="ignore")
color_encoded = ohe.fit_transform(df[["color"]])

# Build a labelled DataFrame from the result
col_names = ohe.get_feature_names_out(["color"])
color_df = pd.DataFrame(color_encoded, columns=col_names, dtype=int)

print(color_df)

Output:

   color_blue  color_green  color_red
0           0            0          1
1           0            1          0
2           1            0          0
3           0            1          0
4           0            0          1

handle_unknown='ignore' riempie le categorie non viste con tutti zeri invece di generare un errore quando arrivano nuovi dati al momento della predizione.

Eliminare una Colonna per Evitare la Multicollinearità

Con tre categorie si ottengono tre colonne binarie, ma la terza è completamente predicibile dalle altre due (blue = 1 − green − red). Questa trappola della variabile dummy può causare problemi nei modelli lineari. Elimina una colonna con drop='first':

ohe_nodrop = OneHotEncoder(sparse_output=False, drop="first", handle_unknown="ignore")
reduced = ohe_nodrop.fit_transform(df[["color"]])
print(pd.DataFrame(reduced, columns=ohe_nodrop.get_feature_names_out(["color"]), dtype=int))

Output (una colonna eliminata):

   color_green  color_red
0            0          1
1            1          0
2            0          0
3            1          0
4            0          1

I modelli basati su alberi (alberi decisionali, random forest, gradient boosting) sono immuni alla trappola della variabile dummy, quindi eliminare una colonna è facoltativo per loro.

pd.get_dummies — L'Alternativa Rapida di Pandas

Per l'analisi esplorativa, pd.get_dummies() è il modo più veloce per applicare il one-hot encoding a un DataFrame:

dummies = pd.get_dummies(df[["color", "size"]], dtype=int)
print(dummies)

Output:

   color_blue  color_green  color_red  size_L  size_M  size_S
0           0            0          1       0       0       1
1           0            1          0       0       1       0
2           1            0          0       1       0       0
3           0            1          0       0       0       1
4           0            0          1       0       1       0

Limitazione: pd.get_dummies() non è un trasformatore addestrato. Non può garantire lo stesso insieme di colonne tra le suddivisioni di training e test, e non supporta handle_unknown. Per le pipeline di produzione, preferire OneHotEncoder all'interno di una Pipeline di scikit-learn.

Evitare il Data Leakage

Il data leakage si verifica quando le informazioni del set di test influenzano la preparazione dei dati di addestramento. Il risultato è un punteggio di valutazione eccessivamente ottimistico che non riflette le prestazioni reali.

Il pattern corretto è:

  1. Dividere i dati in set di training e test prima.
  2. Addestrare qualsiasi encoder solo sul set di training.
  3. Usare transform() (non fit_transform()) sul set di test.
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder

X = df[["color", "size"]]
y = df["price"]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)

ohe = OneHotEncoder(sparse_output=False, handle_unknown="ignore")
ohe.fit(X_train)                       # fit on training data only

X_train_enc = ohe.transform(X_train)  # transform training set
X_test_enc  = ohe.transform(X_test)   # transform test set using training-fit encoder

Per i dettagli sulla suddivisione training/test, consulta il capitolo Train/Test Split.

Utilizzare una Pipeline per Combinare la Codifica con un Modello

Una Pipeline di scikit-learn collega un trasformatore e uno stimatore. Questo garantisce che l'encoder venga sempre addestrato solo sui dati di training, anche durante la cross-validation.

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.linear_model import LinearRegression
from sklearn.compose import ColumnTransformer
from sklearn.model_selection import train_test_split

categorical_cols = ["color", "size"]
numeric_cols     = ["in_stock"]

X_full = df[categorical_cols + numeric_cols]
y_full = df["price"]

X_tr, X_te, y_tr, y_te = train_test_split(X_full, y_full, test_size=0.4, random_state=42)

preprocessor = ColumnTransformer(transformers=[
    ("ohe", OneHotEncoder(handle_unknown="ignore"), categorical_cols),
    ("pass", "passthrough", numeric_cols),
])

pipe = Pipeline(steps=[
    ("preprocessor", preprocessor),
    ("model", LinearRegression()),
])

pipe.fit(X_tr, y_tr)
print("Test predictions:", pipe.predict(X_te))

Il ColumnTransformer applica fasi di preprocessing diverse a colonne diverse in un'unica passata. La pipeline è il pattern raccomandato per tutti i flussi di lavoro di machine learning in produzione.

Scegliere la Codifica Giusta

SituazioneCodifica consigliata
Variabile target (y)LabelEncoder
Feature ordinale (ordine naturale esistente)OrdinalEncoder con categories esplicite
Feature nominale, bassa cardinalitàOneHotEncoder (o pd.get_dummies per l'esplorazione)
Feature nominale, alta cardinalitàTarget encoding o frequency encoding (vedi nota sotto)
Pipeline di produzioneOneHotEncoder dentro una Pipeline / ColumnTransformer

Il target encoding sostituisce ogni categoria con la media della variabile target per quella categoria. Gestisce bene l'alta cardinalità ma è particolarmente soggetto al data leakage — applicarlo sempre con fold di cross-validation oppure usare un'implementazione di libreria (es. category_encoders.TargetEncoder) che lo gestisce automaticamente.

Capitoli Correlati

  • Scale — normalizzare e standardizzare le feature numeriche prima della modellazione
  • Train/Test Split — suddividere correttamente i dati prima di qualsiasi fase di preprocessing
  • Linear Regression — un modello che trae vantaggio dalla corretta codifica categoriale
  • Cross Validation — valutare i modelli in modo affidabile quando combinati con pipeline di codifica
  • Confusion Matrix — misurare le prestazioni del modello di classificazione dopo la codifica dei target
  • Pandas Tutorial — fondamenti di pandas incluse la creazione e la manipolazione dei DataFrame
Was this page helpful?