W3docs

Dados Categóricos

Aprenda a codificar dados categóricos em Python com Label Encoding, Ordinal Encoding, One-Hot Encoding e pd.get_dummies com exemplos do scikit-learn.

Dados categóricos são quaisquer dados que assumem um conjunto limitado e fixo de valores — pense em "red", "blue", "green" para uma coluna de cor, ou "low", "medium", "high" para uma classificação de gravidade. A maioria dos algoritmos de machine learning trabalha com números, portanto as colunas categóricas devem ser convertidas para uma representação numérica antes do treinamento.

Este capítulo explica as principais estratégias de codificação, quando escolher cada uma delas e como aplicá-las corretamente em Python usando pandas e scikit-learn sem vazar informações do conjunto de teste para o seu modelo.

Por que a Codificação é Importante

Fornecer valores de string brutos a um estimador do scikit-learn gera um ValueError. Mesmo quando uma coluna já contém números — como 1, 2, 3 representando "small", "medium", "large" — um algoritmo que trata os valores de features como números contínuos inferirá um relacionamento falso (por exemplo, "large" é três vezes maior que "small"). A codificação permite representar o relacionamento real com precisão.

A escolha da codificação depende de duas perguntas:

  1. Existe uma ordem natural? Cor não tem ordem natural (nominal). Tamanho de camiseta tem uma ordem natural (ordinal). A codificação correta preserva a ordem quando ela existe e a ignora quando não existe.
  2. Quantos valores distintos (cardinalidade) a coluna possui? Colunas de alta cardinalidade (centenas de cidades únicas, IDs de produtos) podem criar milhares de colunas dummy com One-Hot Encoding, o que prejudica tanto a memória quanto o desempenho do modelo.

Configurando um Dataset de Exemplo

Os exemplos abaixo utilizam um pequeno dataset de vestuário para que você possa acompanhar a saída exatamente.

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)

Saída:

   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

Label Encoding substitui cada categoria por um inteiro. O LabelEncoder do scikit-learn atribui inteiros em ordem alfabética.

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

Saída:

   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 (ordem alfabética).

Quando usar: Label Encoding é destinado à variável alvo (y), não às features de entrada. Aplicado a uma coluna de feature nominal, os inteiros codificados implicam uma ordenação que não existe, o que induz a erros em modelos baseados em árvores e é prejudicial para modelos lineares.

Revertendo a codificação:

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

Ordinal Encoding

Ordinal Encoding é semelhante ao Label Encoding, mas permite especificar a ordem exata das categorias. Use-o para features em que a ordem é significativa.

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

Saída:

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

O modelo agora pode inferir corretamente que L (2) > M (1) > S (0).

Tratando categorias desconhecidas no momento da predição:

# 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

One-Hot Encoding cria uma coluna binária por categoria. Um 1 em uma coluna indica que a linha pertence àquela categoria; todas as outras colunas recebem 0. Esta é a escolha padrão para features nominais (sem ordem) fornecidas a modelos lineares, SVMs e redes neurais.

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)

Saída:

   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' preenche categorias não vistas com zeros em vez de gerar um erro quando novos dados chegam no momento da predição.

Removendo uma Coluna para Evitar Multicolinearidade

Com três categorias você obtém três colunas binárias, mas a terceira é totalmente previsível a partir das outras duas (blue = 1 − green − red). Essa armadilha das variáveis dummy pode causar problemas em modelos lineares. Remova uma coluna com 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))

Saída (uma coluna removida):

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

Modelos baseados em árvores (árvores de decisão, florestas aleatórias, gradient boosting) são imunes à armadilha das variáveis dummy, portanto remover uma coluna é opcional para eles.

pd.get_dummies — A Alternativa Rápida do Pandas

Para trabalho exploratório, pd.get_dummies() é a maneira mais rápida de aplicar one-hot encoding a um DataFrame:

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

Saída:

   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

Limitação: pd.get_dummies() não é um transformador ajustável. Não pode garantir o mesmo conjunto de colunas entre divisões de treinamento e teste, e não suporta handle_unknown. Para pipelines em produção, prefira OneHotEncoder dentro de um Pipeline do scikit-learn.

Evitando Vazamento de Dados

Vazamento de dados ocorre quando informações do conjunto de teste influenciam a forma como os dados de treinamento são preparados. O resultado é uma pontuação de avaliação excessivamente otimista que não reflete o desempenho no mundo real.

O padrão correto é:

  1. Divida os dados em conjuntos de treinamento e teste primeiro.
  2. Ajuste qualquer codificador apenas no conjunto de treinamento.
  3. Use transform() (não fit_transform()) no conjunto de teste.
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

Para mais detalhes sobre a divisão treino/teste, consulte o capítulo Train/Test Split.

Usando um Pipeline para Combinar Codificação com um Modelo

Um Pipeline do scikit-learn encadeia um transformador e um estimador. Isso garante que o codificador seja sempre ajustado apenas nos dados de treinamento, inclusive durante a validação cruzada.

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

O ColumnTransformer aplica diferentes etapas de pré-processamento a colunas diferentes em uma única passagem. O pipeline é o padrão recomendado para todos os fluxos de trabalho de machine learning em nível de produção.

Escolhendo a Codificação Correta

SituaçãoCodificação recomendada
Variável alvo (y)LabelEncoder
Feature ordinal (ordem natural existe)OrdinalEncoder com categories explícito
Feature nominal, baixa cardinalidadeOneHotEncoder (ou pd.get_dummies para exploração)
Feature nominal, alta cardinalidadeTarget encoding ou frequency encoding (veja nota abaixo)
Pipeline de produçãoOneHotEncoder dentro de um Pipeline / ColumnTransformer

Target encoding substitui cada categoria pela média da variável alvo para aquela categoria. Lida bem com alta cardinalidade, mas é especialmente propenso ao vazamento de dados — sempre aplique-o com folds de validação cruzada ou use uma implementação de biblioteca (por exemplo, category_encoders.TargetEncoder) que trate isso automaticamente.

Capítulos Relacionados

  • Scale — normalize e padronize features numéricas antes da modelagem
  • Train/Test Split — divida os dados corretamente antes de qualquer etapa de pré-processamento
  • Linear Regression — um modelo que se beneficia de uma codificação categórica adequada
  • Cross Validation — avalie modelos de forma confiável quando combinado com pipelines de codificação
  • Confusion Matrix — meça o desempenho de modelos de classificação após codificar os alvos
  • Pandas Tutorial — fundamentos do pandas incluindo criação e manipulação de DataFrames
Was this page helpful?