pandas: типы столбцов и очистка по правилу

Текстовые столбцы: нормализация и разбор через .str

Содержание курса

Нормализация текста: .str.lower, .str.strip, .str.replace

Самая частая причина, по которой одинаковые значения не совпадают при сравнении — это лишние пробелы и разный регистр. Строки 'Alice', ' alice ' и 'ALICE' для Python разные, хотя по смыслу одно и то же. Три метода закрывают этот класс проблем.

.str.strip() убирает пробельные символы с обоих концов строки — пробелы, табуляции, переносы строк. Если нужно чистить только одну сторону, есть .str.lstrip() (левый конец) и .str.rstrip() (правый).

.str.lower() приводит все символы к нижнему регистру. Для верхнего — .str.upper(), для заглавной первой буквы — .str.capitalize().

.str.replace(pat, repl) заменяет вхождения pat на repl. В pandas 2.x параметр regex=False по умолчанию, то есть pat трактуется буквально.

На практике эти три метода почти всегда идут цепочкой:

import pandas as pd

df = pd.DataFrame({
    'name': ['  Alice Smith ', '  BOB jones', 'carol BROWN  ']
})

df['name_clean'] = df['name'].str.strip().str.lower()
print(df['name_clean'].tolist())
# ['alice smith', 'bob jones', 'carol brown']

Сначала снимаем пробелы по краям, потом приводим к нижнему регистру. Порядок здесь не критичен для этих двух методов, но привычка ставить strip первым полезна: тогда последующие операции работают с уже чистым текстом.

Для замены, например, дефисов на подчёркивания:

df['name_underscored'] = df['name_clean'].str.replace(' ', '_', regex=False)
print(df['name_underscored'].tolist())
# ['alice_smith', 'bob_jones', 'carol_brown']

Ловушка с regex в .str.replace и .str.contains. Здесь легко ошибиться, потому что у двух методов разные дефолты.

В .str.replaceregex=False по умолчанию. Это значит, что строка '.' будет искаться буквально как точка, а не как «любой символ» из регулярных выражений. Если вы хотите использовать паттерн вроде r'\s+', нужно явно написать regex=True.

В .str.contains — наоборот, regex=True по умолчанию. Паттерн '.' там найдёт что угодно, потому что точка в регулярных выражениях означает любой символ.

Антипример:

s = pd.Series(['3.14', '314', 'abc'])

# Хотим найти строки с буквальной точкой:
print(s.str.contains('.'))          # regex=True по умолчанию — найдёт всё!
# 0    True
# 1    True
# 2    True

print(s.str.contains('.', regex=False))  # правильно — только '3.14'
# 0     True
# 1    False
# 2    False

Правило простое: для буквального поиска в .str.contains всегда передавайте regex=False. Для .str.replace с простой подстрокой regex=False уже стоит по умолчанию и менять его не нужно.

Каждый вызов возвращает новый Series — исходный столбец не затрагивается. Если результат нужен в таблице, присваивайте явно: df['col'] = df['col'].str.strip().