Работа с текстовыми колонками в Pandas: символьные данные и их преобразование

Раздел: Python -> Pandas

Основные подходы к обработке строк в Pandas

Наиболее эффективный способ

Как быстро применить строковую операцию ко всем элементам столбца?

Для векторизованной обработки строк используется аксессор .str. Он предоставляет методы, подобные строковым методам Python, но работающие с Series.

import pandas as pd
df = pd.DataFrame({'text': ['Hello', 'WORLD', 'pYTHON', None]})
df['lower'] = df['text'].str.lower()
print(df)

обработка больших данных python (обработка больших данных в python)

     text    lower
0   Hello    hello
1   WORLD    world
2  pYTHON   python
3    None     None

очистка данных python (очистка данных в python)

Метод .str.lower() автоматически обрабатывает пропущенные значения (NaN) без ошибок. Доступны также .str.upper(), .str.title(), .str.capitalize() и другие.

Типичная ошибка:

Попытка вызвать .str на столбце, содержащем нестроковые типы (например, числа), приведет к ошибке AttributeError: 'Series' object has no attribute 'str'. Перед использованием рекомендуется убедиться, что тип данных столбца - object или string. Для преобразования можно выполнить df['col'] = df['col'].astype(str).

Как применить кастомную функцию к каждой строке?

Если нужной операции нет среди методов .str, можно использовать .apply().

def custom_clean(s):
    if s is None:
        return s
    return s.replace(' ', '_').upper()

df['cleaned'] = df['text'].apply(custom_clean)
print(df)

Python подготовка данных (подготовка данных в python)

     text    lower     cleaned
0   Hello    hello      HELLO
1   WORLD    world      WORLD
2  pYTHON   python   PYTHON
3    None     None       None

работа с dataframe python (работа с dataframe в python)

Важно: .apply() медленнее векторизованных методов и может вызвать исключение при работе с NaN, если функция их не обрабатывает. В примере выше проверка if s is None предотвращает ошибку.

Как извлечь часть строки по шаблону с помощью регулярных выражений?

Метод .str.extract() позволяет извлечь подстроки, соответствующие регулярному выражению.

df = pd.DataFrame({'email': ['user@example.com', 'admin@site.org', 'bad-email']})
df[['username','domain']] = df['email'].str.extract(r'([^@]+)@([^@]+)')
print(df)

Python работа с большими данными (работа с большими данными в python)

              email  username      domain
0  user@example.com      user  example.com
1    admin@site.org     admin     site.org
2         bad-email       NaN         NaN

структурированные данные python (структурированные данные в python)

Если шаблон не найден, подставляется NaN. Для нескольких совпадений подойдёт .str.extractall().

Когда стоит использовать list comprehension вместо apply?

Для простых преобразований list comprehension может работать быстрее .apply().

df['upper_lc'] = [x.upper() if x is not None else None for x in df['text']]
print(df)

генерация данных python (генерация данных в python)

     text    lower     cleaned upper_lc
0   Hello    hello      HELLO    HELLO
1   WORLD    world      WORLD    WORLD
2  pYTHON   python     PYTHON   PYTHON
3    None     None       None     None

Python код символа (код символа в python)

Недостаток: list comprehension не интегрируется с индексами DataFrame и не поддерживает автоматическую обработку NaN. При работе с большими данными векторизованные методы .str все же предпочтительнее.

Как обработать целый столбец с помощью строковых методов numpy?

Векторизованные строковые методы numpy можно применить через np.vectorize, но такой подход обычно медленнее .str и редко используется.

Проблема: NaN в строковых операциях

При использовании .str NaN остаются NaN без ошибок. Однако в .apply() необходима явная проверка. Решение: использовать pd.notna() или проверять if pd.isna(x).

def safe_upper(x):
    if pd.isna(x):
        return x
    return x.upper()

df['upper_safe'] = df['text'].apply(safe_upper)

В качестве альтернативы можно удалить или заполнить пропуски перед обработкой.

- обработка символьных данных python (обработка символьных данных в python)
- Python преобразование в строку (преобразование в строку в python)
- Python как проверить строку (проверка строки в python)

Расширенные примеры обработки строк в Pandas

Разделение строк на части и создание новых строк

Метод .str.split() возвращает списки, а .str.explode() превращает их в отдельные строки.

Пример
df = pd.DataFrame({'tags': ['a,b,c', 'd,e', 'f']})
df_exp = df['tags'].str.split(',').explode()
print(df_exp)
0    a
0    b
0    c
1    d
1    e
2    f
dtype: object

Применение: нормализация тегов, создание long format.

Объединение строк столбца с разделителем

.str.cat() объединяет строки столбца в одну строку с разделителем.

Пример
df = pd.DataFrame({'word': ['Python', 'Pandas', 'Data']})
combined = df['word'].str.cat(sep=' - ')
print(combined)
Python - Pandas - Data

Также можно объединить два столбца поэлементно: df['col1'].str.cat(df['col2'], sep=' ').

Поиск всех вхождений шаблона в строке

.str.findall() возвращает список всех совпадений.

Пример
df = pd.DataFrame({'text': ['apple 123', 'banana 456', 'cherry']})
df['numbers'] = df['text'].str.findall(r'\d+')
print(df)
        text numbers
0   apple 123  [123]
1  banana 456  [456]
2      cherry      []

Если нужны просто индексы первого вхождения, используется .str.find().

Удаление лишних пробелов и заполнение пробелами до заданной длины

.str.strip() удаляет пробелы, .str.pad() добавляет пробелы до ширины.

Пример
df = pd.DataFrame({'code': ['  abc  ', 'def', '  ghi ']})
df['stripped'] = df['code'].str.strip()
df['padded'] = df['code'].str.pad(10, side='left', fillchar=' ')
print(df)
      code stripped      padded
0    abc      abc        abc
1      def      def        def
2    ghi      ghi        ghi

Следует помнить: .str.strip() работает только с пробельными символами; для других символов применяется .str.strip(символы).

Извлечение данных с помощью именованных групп в регулярных выражениях

.str.extract() поддерживает именованные группы, что удобно для именования столбцов.

Пример
df = pd.DataFrame({'log': ['2024-01-01 INFO message', '2024-01-02 ERROR fatal']})
df_ext = df['log'].str.extract(r'(?P\d{4}-\d{2}-\d{2})\s+(?P\w+)\s+(?P.+)')
print(df_ext)
        date level      msg
0 2024-01-01  INFO  message
1 2024-01-02 ERROR   fatal

Удаление символов с помощью translate

.str.translate() эффективен для замены набора символов по таблице.

Пример
import string
table = str.maketrans('', '', string.punctuation)
df = pd.DataFrame({'text': ['Hello! How are you?', 'Python: powerful.']})
df['clean'] = df['text'].str.translate(table)
print(df)
                  text                clean
0  Hello! How are you?       Hello How are you
1   Python: powerful.       Python powerful

Таблицы можно создавать и для замены символов, а не только удаления.

Нормализация юникодных строк (например, приведение к одному виду)

.str.normalize() преобразует Unicode строки в заданную форму (NFC, NFD и т.д.).

Пример
df = pd.DataFrame({'text': ['café', 'cafe\u0301']})  # два представления 'café'
df['norm'] = df['text'].str.normalize('NFC')
print(df['norm'].iloc[0] == df['norm'].iloc[1])
True

Полезно при сравнении строк, полученных из разных источников.

Проверка строки на соответствие шаблону с помощью str.match и str.fullmatch

.str.match() ищет совпадение с начала строки, .str.fullmatch() требует совпадение всей строки.

Пример
df = pd.DataFrame({'id': ['A123', 'B456', 'C78']})
df['match_A'] = df['id'].str.match(r'A\d+')
df['full_alpha'] = df['id'].str.fullmatch(r'[A-Z]\d+')
print(df)
     id  match_A  full_alpha
0  A123     True        True
1  B456    False        True
2   C78    False       False

Отличие от .str.contains(): .match() не требует специальных обозначений, проверяет с начала.

Сложная логика с комбинацией методов

Часто требуется несколько преобразований последовательно: lower, удалить знаки, split, взять первый элемент.

Пример
df = pd.DataFrame({'raw': [' Python!   ', '  Data Science? ', ' Machine- Learning ']})
df['processed'] = (df['raw']
                   .str.strip()
                   .str.lower()
                   .str.replace('[!?\-]', '', regex=True)
                   .str.split('\s+')  # разбиваем по пробелам
                   .str[0]  # первое слово
                  )
print(df)
                  raw processed
0       Python!        python
1    Data Science?        data
2  Machine- Learning     machine

Такая цепочка читается легко и выполняется быстро благодаря векторизации.

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

Обработка символьных данных в Python - comments

En
обработка символьных данных python (python)