2026, Jan 12 09:02

Как выбрать столбцы pandas DataFrame по подстрокам и regex

Показываем, как отбирать столбцы pandas DataFrame по подстрокам: строим единый regex для filter, альтернативно формируем список через in и .loc. Простой метод.

Когда нужно выбрать столбцы pandas DataFrame не по точным именам, а по набору подстрок, простое пересечение не спасёт. Такая ситуация часто встречается в аналитических пайплайнах: у вас есть список вроде ["date", "cat", "rabbit"], и вы хотите получить все столбцы, в названии которых встречаются эти токены, например cats_fostered, cats_adopted, rabbits_fostered и т. д.

Постановка задачи

Нужно отфильтровать столбцы по подстрокам из списка. Простое пересечение с именами столбцов не подходит — сохраняются только точные совпадения, а передача списка в фильтрацию по регулярному выражению вызывает ошибку.

import pandas as pd

raw_map = {
    "date": ["2023-01-22","2023-11-16","2024-06-30","2024-08-16","2025-01-22"],
    "cats_fostered": [1,2,3,4,5],
    "cats_adopted": [1,2,3,4,5],
    "dogs_fostered": [1,2,3,4,5],
    "dogs_adopted": [1,2,3,4,5],
    "rabbits_fostered": [1,2,3,4,5],
    "rabbits_adopted": [1,2,3,4,5]
}

pet_df = pd.DataFrame(raw_map)
lookup_terms = ["date", "cat", "rabbit"]

# Не работает: пересечение требует точного совпадения имён столбцов
pet_df[pet_df.columns.intersection(lookup_terms)]

# Не работает: filter(regex=...) ожидает строковый шаблон, а не список
pet_df.filter(regex=lookup_terms)

Что происходит на самом деле

Корневая проблема — несоответствие между точным совпадением и поиском по подстроке. В DataFrame есть столбцы вроде cats_fostered и rabbits_adopted, а в вашем списке — cat и rabbit. Метод columns.intersection(...) сохраняет только те имена, которые в точности равны элементам списка, поэтому остаётся лишь date. При этом DataFrame.filter(regex=...) ожидает одну строку с регулярным выражением, а не список строк, и прямой проход списка приводит к ошибке.

Решение

Соберите единый шаблон регулярного выражения из подстрок и передайте его в filter. Удобно всегда оставлять date, а список сосредоточить на ключах животных. Так вы получите любые столбцы, где в названии встречается cat или rabbit, плюс столбец date.

# Сфокусируйте список только на животных и явно добавьте "date" в шаблон
animal_keys = ["cat", "rabbit"]
regex_rule = "date|" + "|".join(animal_keys)

pet_df.filter(regex=regex_rule)

Если нужен только один вид животного, подход остаётся тем же — просто измените список.

animal_keys = ["cat"]
regex_rule = "date|" + "|".join(animal_keys)

pet_df.filter(regex=regex_rule)

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

animal_keys = ["cat", "rabbit"]
chosen_cols = [c for c in pet_df.columns if c == "date" or any(mark in c for mark in animal_keys)]

pet_df.loc[:, chosen_cols]

Почему это важно

В обработке данных соглашения об именовании столбцов часто несут смысл через префиксы и вставки. Опираться на точные совпадения ненадёжно: это приводит к пустым выборкам или ошибкам. Единый шаблон регулярного выражения или простые строковые проверки делают намерение явным, хорошо масштабируются по мере изменений схемы и предотвращают неожиданные сбои, когда в именах есть суффиксы вроде _fostered или _adopted.

Итоги

Если вы фильтруете столбцы по списку токенов, рассматривайте это как поиск по подстрокам. Соберите одну строку для регулярного выражения через "|".join(...) и передайте её в DataFrame.filter(regex=...), при желании жёстко добавив стабильные столбцы вроде date. Если regex не по душе, сформируйте список столбцов с помощью включения и проверок in или startswith и выбирайте через .loc. Так логика отбора остаётся лаконичной, предсказуемой и легко адаптируемой по мере появления новых однотипно названных столбцов.