22 октября 2026 года вышла pandas 3.1.0, первый выпуск с новыми функциями после pandas 3.0. Разработчики советуют обновиться всем, а главными в списке изменений называют два пункта: read_csv() стал заметно быстрее и научился читать большие файлы в несколько потоков, а у DataFrame появился метод select().
Для тех, у кого pandas крутится в скриптах выгрузки, отчётах и ETL на сервере, выпуск полезен прежде всего скоростью. Но есть и изменения, из-за которых старый код может начать вести себя иначе или сыпать предупреждениями, так что обновлять лучше с прогоном тестов.
DataFrame.select() и filter() с маской
Новый метод select() возвращает таблицу только с нужными столбцами. Кроме имён существующих колонок ему можно передать выражение pd.col() или функцию, и тогда он посчитает новый столбец прямо на ходу. Как и в assign(), следующий аргумент может опираться на столбец, посчитанный в этом же вызове.
df.select("first_name", pd.col("age"), age_months=pd.col("age") * 12)
df.filter(pd.col("a") > 1) # строки, где a больше 1
df.filter(cond=df["a"] > 1) # то же самое через cond
Метод filter() теперь принимает булеву маску через новый аргумент cond, а также функцию или выражение pd.col() позиционно. Это удобно в цепочках методов. Пропуски в маске по умолчанию считаются False. Если передать позиционно список из True и False, pandas выдаст UserWarning: такой список почти наверняка задумывался как маска. Выбор колонок через items, like и regex в будущих версиях объявят устаревшим.
read_csv() в 2-3 раза быстрее и в несколько потоков
Чтение CSV штатным движком engine="c" ускорили на всех этапах: разбор строк, определение типов, преобразование целых, дробных чисел, строк и дат. По данным разработчиков, однопоточное чтение обычно в два-три раза быстрее, чем в 3.0.
Сверху добавили параллельное чтение. Оно включено по умолчанию и срабатывает, если файл локальный, не сжатый, весит не меньше 5 МБ и в вызове нет опций, которым нужен разбор всего файла целиком. Результат совпадает с обычным чтением. Число потоков задаёт новая настройка mode.max_threads: по умолчанию это число доступных процессу ядер, но не больше шести.
На сервере это стоит учитывать. Если pandas работает внутри приложения, которое уже само раскидывает задачи по процессам, например в воркерах Celery или под gunicorn, лишние потоки на каждый read_csv() будут только мешать. Тогда параллельное чтение лучше выключить:
import pandas as pd
with pd.option_context("mode.max_threads", 1):
df = pd.read_csv("large.csv")
# или для всего процесса
pd.set_option("mode.max_threads", 1)
Почтовые индексы и номера счетов в dtype=”category”
Тихое изменение, которое легко пропустить. Раньше read_csv() с dtype="category" на движках c и python делал категории строками даже для числовых колонок. Теперь все движки определяют числовые и логические категории. Так же ведут себя read_table(), read_fwf() и read_excel().
Разработчики прямо предупреждают про колонки-идентификаторы: номера счетов или почтовые индексы с ведущими нулями станут целыми числами, и нули пропадут. Чтобы оставить строки, колонку надо читать как str и уже потом переводить в категории:
df = pd.read_csv("clients.csv", dtype={"zip": "str"})
df["zip"] = df["zip"].astype("category")
inplace=True объявлен устаревшим
По PDEP-8 аргумент inplace объявлен устаревшим у методов, которые на самом деле никогда не меняли данные на месте: drop(), rename(), rename_axis(), reset_index(), set_index(), dropna(), drop_duplicates(), sort_values(), sort_index(), eval() и query(). Под капотом там всё равно создавался новый объект и присваивался обратно, а с Copy-on-Write из pandas 3.0 лишней копии и так нет. У fillna() и replace(), которые действительно умеют менять значения на месте, аргумент остаётся.
# было df.reset_index(inplace=True) # стало df = df.reset_index()
Устарело и .values для колонок с часовым поясом, периодами и интервалами: сейчас оно теряет данные, например часовой пояс, а в pandas 4.0 будет возвращать ExtensionArray. Вместо него разработчики советуют .array или .to_numpy().
NumPy 2 и другие зависимости
pandas 3.1 больше не работает с NumPy 1.x: минимальная версия теперь 2.0.2, а python-dateutil нужен не ниже 2.9.0. Подняли и минимальные версии необязательных библиотек, например pyarrow 16.0.0, SQLAlchemy 2.0.42 и matplotlib 3.10.5. Для сборки из исходников нужен компилятор с C++20.
Ещё одна деталь для серверов: pandas перестал использовать numexpr 2.14.1 для ускорения арифметики. Отдельные сборки этой версии иногда молча возвращали неверный результат, например колонку из нулей. Теперь pandas в этом случае откатывается на NumPy и один раз предупреждает, а eval() и query() с явным engine="numexpr" падают с ImportError. Чтобы вернуть ускорение, нужен numexpr 2.14.2 или новее.
python -m pip install --upgrade pandas python -c "import pandas, numpy; print(pandas.__version__, numpy.__version__)"
Итог: pandas 3.1 стоит ставить ради read_csv(), особенно если вы гоняете большие выгрузки. Перед обновлением проверьте, что в окружении NumPy 2, нет numexpr 2.14.1, а колонки с ведущими нулями не читаются через dtype="category". Предупреждения про inplace код не ломают, но заменить такие вызовы на присваивание лучше сразу.