Приведение несогласованных категорий к единому виду
Нормализуйте текстовые столбцы категорий, сопоставляя псевдонимы, исправляя опечатки нечётким сопоставлением и применяя канонический список.
«Приведение несогласованных категорий к единому виду» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Части этого урока еще не переведены и отображаются на английском.
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.
Часто задаваемые вопросы
Урок «Приведение несогласованных категорий к единому виду» бесплатный?
Да — полный текст урока «Приведение несогласованных категорий к единому виду» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Чему я научусь в уроке «Приведение несогласованных категорий к единому виду»?
Нормализуйте текстовые столбцы категорий, сопоставляя псевдонимы, исправляя опечатки нечётким сопоставлением и применяя канонический список. Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?
Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Приведение несогласованных категорий к единому виду»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?
Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Поиск и удаление дубликатов
- Поиск и обработка выбросов
- Приведение несогласованных категорий к единому виду
- Проверка схемы и утверждения