---
title: One-Hot Encoding vs Label Encoding in Python: When to Use Which
source: https://app.sythra.ai/learn/machine-learning/one-hot-encoding-vs-label-encoding-python
topic: Machine Learning
updated: 2026-08-28
publisher: Sythra (https://app.sythra.ai)
---

# One-Hot Encoding vs Label Encoding in Python: When to Use Which

One-Hot Encoding converts categorical data into binary (0/1) indicator columns for each category (best for nominal data), while Label Encoding converts categories into sequential integers (best for ordinal data with a natural hierarchy).

_Source: [https://app.sythra.ai/learn/machine-learning/one-hot-encoding-vs-label-encoding-python](https://app.sythra.ai/learn/machine-learning/one-hot-encoding-vs-label-encoding-python) — free to read on Sythra._

## Key points

- Explains nominal vs. ordinal categorical data and how to pick the right encoder.
- Details the fake ranking trap ($2 > 1 > 0$) and the dummy variable trap.
- Provides complete from-scratch and production Scikit-Learn code.
- Highlights why OrdinalEncoder should be used on feature matrices instead of LabelEncoder.

**One-Hot Encoding** and **Label Encoding** are the two foundational techniques used in data science to convert categorical (text-based) data into machine-readable numeric formats — One-Hot Encoding creates a distinct binary ($0$ or $1$) indicator column for each category, while Label Encoding assigns each category a single integer.

Think of it like sorting fruits for a computer that cannot read words: **Label Encoding** is like slapping a numbered sticker on each fruit (Apple = 1, Banana = 2, Mango = 3). **One-Hot Encoding** is like giving each fruit its own dedicated tray with a checkbox ("Is it an Apple?", "Is it a Banana?", "Is it a Mango?"). Both achieve the goal of numerical conversion, but picking the wrong one can mislead your algorithm into finding fake mathematical patterns that do not exist.

## Why Categorical Encoding Is Necessary in Python

Machine learning algorithms are mathematical engines — they compute matrix multiplications, Euclidean distances, and gradient slopes. They cannot perform arithmetic on string values like `"Delhi"`, `"Mumbai"`, or `"Small"`, `"Large"`.

Attempting to pass raw text columns into Scikit-Learn models will immediately trigger a `ValueError: could not convert string to float`. Converting text to numbers is mandatory, but how you convert it determines whether your model learns real signals or spurious correlations.

## The Intuition: Nominal vs. Ordinal Data

To pick the right encoding technique, you must determine whether your categories possess a natural, meaningful hierarchy:

| Data Category | Has Natural Hierarchy? | Real-World Examples | Recommended Method |
| --- | --- | --- | --- |
| **Nominal Data** | **NO** (No category is mathematically "greater" than another) | City (Delhi, Mumbai, Chennai), Device (iOS, Android, Windows), Color (Red, Blue). | **One-Hot Encoding** (prevents fake rankings). |
| **Ordinal Data** | **YES** (Categories follow a clear, natural order) | Customer Tier (Bronze < Silver < Gold), Education (High School < Bachelors < PhD), Size (Small < Medium < Large). | **Ordinal Encoding** (preserves true hierarchy efficiently). |

## The Fake Ranking Trap in Label Encoding

Suppose you have a `City` column with `Delhi`, `Mumbai`, and `Chennai`. If you encode them with Label Encoding as $0, 1, 2$, a linear regression model calculates a single slope weight $\beta \cdot \text{City}$. The model will mathematically assume that **Chennai ($2$) is twice as much as Mumbai ($1$)**, and that Chennai is "greater than" Delhi ($0$).

Because cities have no numerical ranking, this introduces artificial bias into linear models, support vector machines, and distance-based algorithms like KNN. One-Hot Encoding solves this by ensuring all categories are equidistant in geometric space.

## The Mathematical Foundations

### 1. Label / Ordinal Encoding Formulation

Maps each category to an integer index from $0$ to $n-1$:

$$f(\text{category}_i) = i, \quad i \in \{0, 1, 2, \dots, n-1\}$$

### 2. One-Hot Encoding Formulation

For $n$ unique categories, creates an $n$-dimensional binary vector where exactly one element equals $1$ and the rest equal $0$:

$$\text{col}_j = \begin{cases} 1 & \text{if } j = k \\ 0 & \text{if } j \neq k \end{cases} \quad \text{for } j = 1, 2, \dots, n$$

### 3. The Dummy Variable Trap (Multicollinearity)

When One-Hot Encoding $n$ categories, the sum of all $n$ columns always equals $1$ ($c_1 + c_2 + \dots + c_n = 1$). This creates **perfect multicollinearity** in linear models, making matrix inversion ($(\mathbf{X}^T\mathbf{X})^{-1}$) unstable. Dropping the first column (using $n-1$ dummy variables with `drop='first'`) resolves this while preserving 100% of the information.

## Model Reaction Matrix: How Algorithms Behave

| Algorithm Family | Response to One-Hot Encoding | Response to Label / Ordinal Encoding |
| --- | --- | --- |
| **Linear & Logistic Regression** | **Recommended** (use `drop='first'` to prevent multicollinearity). | **Harmful for Nominal data** (forces an unintended linear slope $\beta$). |
| **Distance-Based (KNN, SVM, K-Means)** | **Recommended** (all categories are equidistant with Euclidean distance $\sqrt{2}$). | **Harmful** (falsely calculates distance $d(\text{Delhi}, \text{Chennai}) = 2$ vs $d(\text{Delhi}, \text{Mumbai}) = 1$). |
| **Tree-Based (Random Forest, XGBoost)** | Works, but creates wide sparse trees on high cardinality features. | **Excellent** (trees make split thresholds like $x \le 1.5$ without assuming linear scales). |

## Code: Step-by-Step Python Implementation

### 1. Setting Up the Sample Dataset

```python
import pandas as pd
import numpy as np

# Sample realistic e-commerce transactions dataset
data = {
    "city": ["Delhi", "Mumbai", "Chennai", "Delhi", "Mumbai"],
    "size": ["Small", "Large", "Medium", "Small", "Large"],
    "price": [200, 450, 300, 210, 470]
}

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

### 2. Label / Ordinal Encoding — From Scratch

```python
def ordinal_encode_scratch(column, order_list=None):
    if order_list is not None:
        mapping = {category: idx for idx, category in enumerate(order_list)}
    else:
        unique_cats = column.unique()
        mapping = {category: idx for idx, category in enumerate(unique_cats)}
    return column.map(mapping), mapping

# Ordinal encoding with a defined order: Small (0) < Medium (1) < Large (2)
df["size_encoded_scratch"], size_mapping = ordinal_encode_scratch(
    df["size"], order_list=["Small", "Medium", "Large"]
)
print(df[["size", "size_encoded_scratch"]])
print("Mapping Dictionary:", size_mapping)
```

### 3. Ordinal Encoding with Scikit-Learn (Production Version)

_Pro Tip:_ Always use `OrdinalEncoder` for input feature matrix $X$ rather than `LabelEncoder` (which is reserved exclusively for the 1D target label $y$):

```python
from sklearn.preprocessing import OrdinalEncoder

# Explicitly declare category order
ordinal_enc = OrdinalEncoder(
    categories=[["Small", "Medium", "Large"]],
    handle_unknown="use_encoded_value",
    unknown_value=-1
)
df["size_ordinal_sklearn"] = ordinal_enc.fit_transform(df[["size"]])
print(df[["size", "size_ordinal_sklearn"]])
```

### 4. One-Hot Encoding — From Scratch

```python
def one_hot_encode_scratch(df, column_name):
    categories = df[column_name].unique()
    encoded_df = pd.DataFrame(index=df.index)
    for cat in categories:
        encoded_df[f"{column_name}_{cat}"] = (df[column_name] == cat).astype(int)
    return encoded_df

city_onehot_scratch = one_hot_encode_scratch(df, "city")
print(city_onehot_scratch)
```

### 5. One-Hot Encoding with Pandas & Scikit-Learn

```python
# Option A: Quick Pandas get_dummies (ideal for EDA)
df_dummies = pd.get_dummies(df["city"], prefix="city", drop_first=True)
print("--- Pandas get_dummies (drop_first=True) ---")
print(df_dummies)

# Option B: Scikit-Learn OneHotEncoder (ideal for ML Pipelines)
from sklearn.preprocessing import OneHotEncoder

ohe = OneHotEncoder(sparse_output=False, drop="first", handle_unknown="ignore")
city_encoded = ohe.fit_transform(df[["city"]])
city_df = pd.DataFrame(city_encoded, columns=ohe.get_feature_names_out(["city"]))
print("
--- Scikit-Learn OneHotEncoder ---")
print(city_df)
```

## Side-by-Side Comparison of Output

| Original City | Label Encoded (Single Column) | One-Hot: city_Delhi | One-Hot: city_Mumbai | One-Hot: city_Chennai |
| --- | --- | --- | --- | --- |
| Delhi | 0 | 1 | 0 | 0 |
| Mumbai | 1 | 0 | 1 | 0 |
| Chennai | 2 | 0 | 0 | 1 |
| Delhi | 0 | 1 | 0 | 0 |
| Mumbai | 1 | 0 | 1 | 0 |

## Common Pitfalls & Best Practices

- **Using LabelEncoder on Features:** `LabelEncoder` is designed strictly for the 1D target column $y$. For 2D feature matrix $X$, use `OrdinalEncoder` or `OneHotEncoder` to maintain pipeline compatibility.
- **The High Cardinality Explosion:** One-Hot Encoding a column with 10,000 unique postal codes creates 10,000 sparse columns, consuming gigabytes of memory. Use Frequency Encoding or Target Encoding instead.
- **Data Leakage at Test Time:** Always fit your encoder strictly on `X_train` (`encoder.fit(X_train)`) and only transform on `X_test` (`encoder.transform(X_test)`). Set `handle_unknown='ignore'` so unexpected test categories do not crash your pipeline.

## Summary: The Quick Decision Checklist

- Use **One-Hot Encoding** for nominal (unordered) categories like cities, colors, and brands.
- Use **Ordinal Encoding** for ordinal (ranked) categories like ratings, sizes, and education levels.
- Use `drop='first'` in One-Hot Encoding when training linear models to avoid multicollinearity.
- Tree-based algorithms (Random Forests, XGBoost) handle integer encoding well, while distance-based models (KNN, SVM) require One-Hot Encoding.
- Always fit encoders exclusively on training sets to prevent data leakage.

## FAQ

### What is the difference between One-Hot Encoding and Label Encoding?

One-Hot Encoding creates a new binary 0/1 column for every unique category, preventing any artificial ranking. Label Encoding maps each category to a single integer in a single column.

### When should I use One-Hot Encoding over Label Encoding?

Use One-Hot Encoding for nominal (unordered) variables like cities, product categories, or device types, especially when training linear models, SVMs, or KNN.

### What is the Dummy Variable Trap in One-Hot Encoding?

The Dummy Variable Trap occurs when all n category columns are included in a linear regression, causing perfect multicollinearity because one column can be perfectly predicted from the others. Using drop=first (n-1 columns) resolves this.

### Why should I use OrdinalEncoder instead of LabelEncoder in Scikit-Learn?

In Scikit-Learn, LabelEncoder is designed exclusively for 1D target labels (y), while OrdinalEncoder is built for 2D input feature matrices (X) and allows explicit ordering and pipeline integration.

---

Written by Sythra — Learn machine learning by building. Practice this topic with Sythra's AI tutor: https://app.sythra.ai/pricing
