2025, Dec 16 06:01

Как правильно форматировать числа с разделителем тысяч в pandas

Почему форматирование в pandas не применяется на месте и как показать разделитель тысяч: Styler, to_string, параметр thousands и преобразование данных.

Форматирование чисел с разделителем тысяч в pandas кажется простым, но есть распространённая ловушка: стилизация не применяется «на месте». Если вызвать Styler, а затем распечатать DataFrame, визуально ничего не меняется — и складывается ощущение, что ваш пользовательский форматтер игнорируется. Ниже — как сделать это надёжно и эффективно.

Обзор проблемы

Нужно отобразить целые числа с разделителем тысяч. DataFrame читается из .xlsx-файла, определяется простой форматтер, который добавляет запятые к целым. Однако при печати DataFrame форматирования не видно, и кажется, что форматтер вообще не вызывается.

Воспроизводимый пример

Ниже — минимальный пример. Он читает лист, задаёт форматтер, применяет style.format и затем печатает DataFrame.

import pandas as pd
SRC_FILE = "/Volumes/Spare/Downloads/prize-june-2025.xlsx"
def comma_group(n):
    return f"{n:,d}" if isinstance(n, int) else n
frame = pd.read_excel(SRC_FILE, header=2, usecols="B,C,E:H")
print(frame.dtypes)
frame.style.format(comma_group)
print(frame.head())

Вывод показывает «сырые» целые числа без разделителей. Похоже, comma_group так и не запускается.

Почему так происходит

Стилизация в pandas — это слой представления. Выражение DataFrame.style возвращает объект Styler, который умеет рендерить ваш DataFrame с заданным форматированием, как правило, в HTML. Он не изменяет исходный DataFrame и не влияет на методы DataFrame вроде head или print. Поэтому вызов style.format, а затем печать исходного DataFrame показывает неизменённые значения.

Есть и второй нюанс при работе в ноутбуках: отрендеренный вывод Styler отображается только если объект Styler — последнее значение в ячейке. В противном случае он создаётся и тут же «забывается», не оставляя видимого результата.

Рабочее решение

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

frame.style.format(comma_group)

Если нужен текстовый вывод (например, в скрипте или консоли) вместо HTML, преобразуйте Styler в строку и распечатайте её:

print(frame.style.format(comma_group).to_string())

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

Более быстрые встроенные форматы

Пользовательская функция-форматтер работает, но она относительно медленная. Когда числовые столбцы имеют однородные типы, используйте встроенный параметр thousands — это проще и быстрее:

frame.style.format(thousands=',')

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

frame.style.format({col: '{:,d}' for col in frame.select_dtypes('number')})

Если нужно глобально повлиять на отображение чисел с плавающей точкой, можно изменить формат по умолчанию через pd.options.display.float_format.

Преобразование самих данных (а не только отображения)

Если требуется реально превратить значения в строки с разделителями и дальше работать с DataFrame (уже строковым), примените функцию ко всему DataFrame и сохраните результат:

result = frame.map(comma_group)

Это создаст новый строковый DataFrame, не затрагивая исходные данные.

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

Разделение представления и самих данных — ключ к корректности и производительности. Стилизация отлично подходит для отображения и экспорта, но не меняет содержимое DataFrame. Ожидание «встроенного» форматирования приводит к путанице, вводящим в заблуждение распечаткам и лишней самописной логике там, где достаточно встроенного параметра.

Итоги и рекомендации

Используйте API Styler, когда вам нужен отформатированный вывод: возвращайте Styler последним выражением в ячейке ноутбука или преобразуйте его в строку для консоли. Предпочитайте параметр thousands как лаконичное и быстрое решение, а при необходимости поколоночного контроля задавайте словарь форматов. Если нужно хранить данные именно как форматированные строки, применяйте свой форматтер к DataFrame. Чёткое разграничение этих сценариев сэкономит время и избавит от сюрпризов в рабочих процессах с pandas.