0Pricing
Pandas & NumPy Academy · Lección

Estandarizar categorías inconsistentes

Normalice las columnas de categorías de texto libre asignando alias, corrigiendo errores tipográficos con coincidencia aproximada y aplicando una lista canónica.

Estandarizar categorías inconsistentes es una lección gratuita de Pandas & NumPy Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Pandas & NumPy Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.

Partes de esta lección aún no han sido traducidas y se muestran en inglés.

The Problem of Inconsistent Categories

When category data is entered by humans, the same concept appears under many different spellings: Electronics, electronics, ELECTRONICS, Electronicss. A groupby on this column produces dozens of tiny groups instead of one meaningful group. Standardising categories into a canonical list is one of the most important cleaning steps before any aggregation or machine learning feature creation.

import pandas as pd

df = pd.read_csv('products.csv')
print(df['category'].value_counts().head(20))

Normalising Case and Whitespace

The first and easiest standardisation step is normalising case and whitespace. Apply .str.strip().str.lower() to remove leading/trailing spaces and convert everything to lowercase before any other comparison. This single step collapses many variants: Electronics, electronics, and ' Electronics ' all become electronics after normalisation.

df['category_clean'] = df['category'].str.strip().str.lower()

print('Before:', df['category'].nunique())
print('After:', df['category_clean'].nunique())

Mapping Aliases with a Dict

After case normalisation, many variants are still distinct due to abbreviations, synonyms, or legacy names. Build an alias mapping dictionary where keys are variant spellings and values are the canonical form. Apply it with df['category_clean'].map(alias_map).fillna(df['category_clean']) — the fillna preserves values not in the dictionary rather than replacing them with NaN.

alias_map = {
    'elect': 'electronics',
    'elec': 'electronics',
    'tech': 'electronics',
    'clothing': 'apparel',
    'clothes': 'apparel',
    'garments': 'apparel'
}

df['category_clean'] = df['category_clean'].map(alias_map).fillna(df['category_clean'])
print(df['category_clean'].value_counts().head())

Using str.replace for Pattern Fixes

Some category names have consistent formatting errors like double spaces or trailing numbers. Use .str.replace() with a regular expression to fix these patterns across all rows at once. For example, .str.replace(r'\s+', ' ', regex=True) collapses multiple spaces into one, and .str.replace(r'\d+$', '', regex=True) strips trailing digits from category names.

df['category_clean'] = (
    df['category_clean']
    .str.replace(r'\s+', ' ', regex=True)  # collapse spaces
    .str.replace(r'\d+$', '', regex=True)   # strip trailing numbers
    .str.strip()
)

print(df['category_clean'].value_counts())

Fuzzy Matching with difflib

When typos are unpredictable, use fuzzy matching to find the closest canonical category for each variant. Python's built-in difflib.get_close_matches() returns the best matches from a list of valid categories based on string similarity. Apply it as a helper function via df['category'].apply() to resolve variants that map() alone cannot catch.

from difflib import get_close_matches

CANONICAL = ['electronics', 'apparel', 'home', 'sports', 'beauty']

def fuzzy_fix(val):
    matches = get_close_matches(str(val).lower().strip(), CANONICAL, n=1, cutoff=0.7)
    return matches[0] if matches else val

df['category_fuzzy'] = df['category_clean'].apply(fuzzy_fix)
print(df[['category_clean', 'category_fuzzy']].head(10))

Building a Canonical Category List

Define your canonical categories explicitly rather than inferring them from the data. A hard-coded list forces every value through a validation gate; anything not in the list is flagged as unknown. Maintain the canonical list in a config file or a separate DataFrame column so it is easy to update when the business adds a new product category without touching the cleaning code.

CANONICAL_CATEGORIES = {
    'electronics', 'apparel', 'home', 'sports',
    'beauty', 'food', 'toys', 'automotive'
}

df['is_known_category'] = df['category_fuzzy'].isin(CANONICAL_CATEGORIES)
unknown = df[~df['is_known_category']]['category_fuzzy'].unique()
print('Unknown categories remaining:', unknown)

Handling Unknown Categories

Unknown categories that do not match any canonical value after fuzzy fixing should be grouped under an Other label rather than dropped, so you do not silently lose rows. Set them to 'other' with np.where() or a simple conditional assignment. Log how many rows were mapped to 'other' and review them for patterns that might warrant a new canonical category.

import numpy as np

df['category_final'] = np.where(
    df['category_fuzzy'].isin(CANONICAL_CATEGORIES),
    df['category_fuzzy'],
    'other'
)

print(df['category_final'].value_counts())

Enforcing a Categorical Dtype

After standardisation, convert the clean category column to a Pandas Categorical dtype with an explicit list of valid categories. This enforces the schema: any attempt to assign an invalid category raises an error. It also reduces memory by storing category strings as integer codes internally, and speeds up groupby operations on large DataFrames.

df['category_final'] = pd.Categorical(
    df['category_final'],
    categories=list(CANONICAL_CATEGORIES) + ['other']
)

print(df['category_final'].dtype)
print(df['category_final'].cat.categories)

Validating the Clean Column

After all standardisation steps, run a final validation: assert that no value outside the canonical set exists in the cleaned column. Use assert df['category_final'].isin(valid_set).all(). Place this assertion at the end of the cleaning function so it runs every time the pipeline executes, catching regressions when new raw data contains previously unseen category labels.

valid_set = set(CANONICAL_CATEGORIES) | {'other'}

assert df['category_final'].isin(valid_set).all(), 'Invalid category found'
print('All categories valid. Distribution:')
print(df['category_final'].value_counts())

Tracking the Standardisation Changes

Build a diff table showing the original value and its cleaned replacement for every row that changed. This audit trail lets data owners review and approve or reject specific mappings. Use a boolean mask to select changed rows and compare the original and final columns side by side. Export the diff as a CSV for non-technical stakeholders to review.

changed = df['category'] != df['category_final']
diff_table = df[changed][['category', 'category_final']].drop_duplicates()
diff_table.columns = ['original', 'mapped_to']
print(f'Unique mappings applied: {len(diff_table)}')
print(diff_table)

Saving the Standardised Dataset

Replace the original messy category column with the standardised one and drop intermediate working columns before saving. Store the alias mapping dictionary and the fuzzy-fix cutoff threshold in the pipeline config so the standardisation is fully reproducible. A cleaning run two months later on a new data dump should produce identical results for the same input values.

df_out = df.drop(columns=['category_clean', 'category_fuzzy', 'is_known_category'])
df_out = df_out.rename(columns={'category_final': 'category'})

df_out.to_parquet('products_clean.parquet', index=False)
print('Saved. Category distribution:')
print(df_out['category'].value_counts())

Quick Check

Test your understanding of Data Analysis concepts from this lesson.

Lesson Recap

In this lesson you learned: normalising case and whitespace as a first standardisation step, mapping aliases and applying fuzzy matching for typo correction, and enforcing a canonical category list with Categorical dtype and assertions. Next up we explore schema validation and runtime assertions to guard every pipeline stage.

Preguntas frecuentes

¿La lección «Estandarizar categorías inconsistentes» es gratis?

Sí — el texto completo de «Estandarizar categorías inconsistentes» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Pandas & NumPy Academy, actualiza a CoddyKit PRO. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Estandarizar categorías inconsistentes»?

Normalice las columnas de categorías de texto libre asignando alias, corrigiendo errores tipográficos con coincidencia aproximada y aplicando una lista canónica. Practicas Pandas & NumPy Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Pandas & NumPy Academy?

No se requiere experiencia previa. Pandas & NumPy Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Estandarizar categorías inconsistentes»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Pandas & NumPy Academy?

Sí. Cada lección de Pandas & NumPy Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Detectar y eliminar duplicados
  2. Detectar y tratar valores atípicos
  3. Estandarizar categorías inconsistentes
  4. Validación de esquemas y aserciones
← Volver a Pandas & NumPy Academy