to_csv в Pandas — как сохранить данные в файл

Коротко

df.to_csv() сохраняет DataFrame в CSV-файл. Обратная операция к read_csv. На собеседованиях аналитиков спрашивают реже, чем загрузку, но в рабочих задачах экспорт — рутина: выгрузить отчёт для менеджера, сохранить результат расчёта, передать данные коллеге в Excel.

Базовый экспорт

import pandas as pd

df = pd.DataFrame({
    'user_id': [1, 2, 3],
    'city': ['Москва', 'Казань', 'Новосибирск'],
    'revenue': [15000, 8200, 11300]
})

df.to_csv('report.csv')

По умолчанию pandas записывает UTF-8 с запятой-разделителем и добавляет столбец индекса. Почти всегда это не то, что вы хотите — нужны параметры.

Ключевые параметры

index — убрать индекс

df.to_csv('report.csv', index=False)

Без index=False в файле появится лишний безымянный столбец с номерами строк. Это самая частая ошибка при экспорте — и самый частый вопрос на собеседовании про to_csv.

sep — разделитель

# Точка с запятой — чтобы Excel на русской Windows открыл корректно
df.to_csv('report.csv', sep=';', index=False)

# Табуляция
df.to_csv('report.tsv', sep='\t', index=False)

encoding — кодировка

# UTF-8 с BOM — Excel на Windows откроет без кракозябр
df.to_csv('report.csv', encoding='utf-8-sig', index=False)

# cp1251 — старый формат, но гарантированно работает в русском Excel
df.to_csv('report.csv', encoding='cp1251', sep=';', index=False)

utf-8-sig добавляет невидимый маркер (BOM) в начало файла — именно по нему Excel понимает, что файл в UTF-8. Без BOM русские буквы превращаются в кракозябры. Подробнее о кодировках — в гайде по read_csv.

header и columns — управление столбцами

# Без заголовка
df.to_csv('data.csv', header=False, index=False)

# Экспорт только нужных столбцов
df.to_csv('report.csv', columns=['user_id', 'revenue'], index=False)

na_rep — замена пропусков

# Пропуски станут строкой "N/A" вместо пустого значения
df.to_csv('report.csv', na_rep='N/A', index=False)

По умолчанию NaN записывается как пустая строка. Если получатель файла работает в Excel, пустые ячейки могут сбить формулы — na_rep решает проблему.

Дозапись в файл — mode='a'

# Первый раз — создаём файл с заголовком
df_jan.to_csv('yearly.csv', index=False)

# Добавляем данные без повторного заголовка
df_feb.to_csv('yearly.csv', mode='a', header=False, index=False)

mode='a' открывает файл на дозапись (append). Важно передать header=False, чтобы заголовки не дублировались.

Другие форматы экспорта

to_excel

df.to_excel('report.xlsx', sheet_name='Отчёт', index=False)

Нужна библиотека openpyxl. Преимущество: Excel сразу видит кодировку и разделители — никаких кракозябр. Для отчётов стейкхолдерам часто проще отдать xlsx.

to_clipboard

df.to_clipboard(index=False)

Копирует DataFrame в буфер обмена. Вставляете в Excel через Ctrl+V — данные уже в таблице. Удобно при работе в Jupyter.

to_json

df.to_json('data.json', orient='records', force_ascii=False)

force_ascii=False сохраняет кириллицу как есть, а не как \u041c\u043e\u0441\u043a\u0432\u0430. Параметр orient='records' даёт список словарей — самый удобный формат для API.

Практические примеры

Отчёт для менеджера в русском Excel

report = df.groupby('city')['revenue'].sum().reset_index()
report.columns = ['Город', 'Выручка']
report.to_csv('отчёт.csv', sep=';', encoding='cp1251', index=False)

Связка sep=';' + encoding='cp1251' — стандарт для русского Excel на Windows. Если у получателя Mac — используйте encoding='utf-8-sig' с sep=','.

Фильтрованная выгрузка

# Только московские заказы дороже 10 000
big_moscow = df[(df['city'] == 'Москва') & (df['amount'] > 10000)]
big_moscow.to_csv('moscow_big_orders.csv', index=False)

Экспорт результата с пропусками

result = df.pivot_table(values='revenue', index='city', columns='month', aggfunc='sum')
result.to_csv('pivot.csv', na_rep='0')

Здесь index=True оставляем намеренно — города из индекса должны попасть в файл.

Частые ошибки

Лишний столбец с индексом. Забыли index=False — в CSV первый столбец Unnamed: 0 с номерами строк. При повторной загрузке через read_csv этот столбец останется, и с каждым циклом «загрузка-сохранение» будет добавляться новый.

Кракозябры в Excel. Сохранили в UTF-8 без BOM, открыли в Excel на Windows — русский текст нечитаем. Решение: encoding='utf-8-sig' или encoding='cp1251' с sep=';'.

Заголовок дублируется при дозаписи. Используете mode='a', но забыли header=False. В середине файла появляется строка с названиями столбцов — ломает последующую загрузку.

Вопросы с собеседований

-- Как сохранить DataFrame в CSV без индекса? -- df.to_csv('file.csv', index=False). По умолчанию pandas записывает индекс как первый столбец — в большинстве случаев это не нужно.

-- Какую кодировку использовать, чтобы русский CSV корректно открылся в Excel? -- encoding='utf-8-sig' (UTF-8 с BOM) или encoding='cp1251' с sep=';'. BOM-маркер сообщает Excel, что файл в UTF-8. Без него Excel на Windows по умолчанию использует системную кодировку и показывает кракозябры.

-- Как дописать данные в существующий CSV? -- df.to_csv('file.csv', mode='a', header=False, index=False). Параметр mode='a' включает режим append. header=False предотвращает повторную запись заголовков.

-- Чем to_csv отличается от to_excel? -- to_csv создаёт текстовый файл с разделителями. to_excel — бинарный xlsx с поддержкой листов, форматирования и формул. CSV быстрее и легче, xlsx удобнее для получателей, работающих в Excel.

-- Что делает параметр na_rep? -- Заменяет NaN на указанную строку при записи. na_rep='N/A' запишет N/A вместо пустого значения. Полезно, когда получателю нужно явно видеть пропуски.

Потренировать Python-вопросы на практике можно в тренажёре Карьерника. Ещё больше примеров — на странице с вопросами.

Открыть тренажёр в Telegram — вопросы по pandas, SQL и аналитике. Бесплатно.

FAQ

Можно ли сохранить DataFrame в CSV без заголовков?

Да. df.to_csv('file.csv', header=False, index=False). Это нужно при дозаписи в существующий файл или когда принимающая система ожидает данные без строки заголовка. Больше приёмов экспорта — в шпаргалке по pandas.

Как экспортировать только определённые столбцы?

Параметр columns: df.to_csv('file.csv', columns=['user_id', 'revenue'], index=False). Альтернатива — отфильтровать DataFrame до экспорта: df[['user_id', 'revenue']].to_csv('file.csv', index=False). Результат одинаковый.

Как сохранить CSV с разделителем «точка с запятой»?

df.to_csv('file.csv', sep=';', index=False). Точка с запятой — стандартный разделитель для CSV в русской и европейской локали, потому что запятая используется как десятичный разделитель в числах. Excel на русской Windows по умолчанию ожидает именно sep=';'.