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.