«CSV — это просто текст с запятыми. Что может пойти не так?»
— спросил ты. И через пять минут уже плакал, разбирая кодировку, кракозябры и ValueError: could not convert string to float.
Спокойно. Сегодня разберём, как работать с CSV-файлами в Python, не потеряв душевное равновесие. Мы поговорим про pandas, csv, кодировки, странные разделители, мусор в данных, и даже разберём реальные кейсы — от новичковых до взрослых, бородатых задач.
🧰 Что будем использовать?
pip install pandas
А для базовой работы — ещё и модуль csv, который уже есть в стандартной библиотеке Python.
📄 CSV ≠ Excel: В чём подвох?
CSV (Comma-Separated Values) — это просто текст. Он не знает, что такое ширина колонок, стили или формулы. Иногда он вообще не с запятыми, а с точками с запятой. А ещё он может быть в utf-8, cp1251 или Windows-1252. Красота!
🐣 Пример 1: Чтение простого CSV с помощью pandas (новичок)
import pandas as pd
# Читаем CSV
df = pd.read_csv("data.csv")
# Показываем первые 5 строк
print(df.head())
📝 Комментарии:
- pd.read_csv(...) — стандартная функция для чтения CSV.
- head() показывает первые 5 строк, чтобы не грузить всю таблицу.
🔍 Убедись, что data.csv лежит рядом с файлом скрипта или укажи полный путь.
😱 Пример 2: CSV с неправильной кодировкой
Часто приходит файл из 1С, Excel или от коллеги "из бухгалтерии", и вместо текста — иероглифы.
df = pd.read_csv("data.csv", encoding="cp1251")
print(df.head())
📌 Важно:
- Если видишь кракозябры — это, скорее всего, не utf-8.
- Пробуй encoding="cp1251" или encoding="ISO-8859-1" — чаще всего срабатывает.
🪤 Пример 3: CSV с нестандартным разделителем
Иногда CSV — это не про запятые. В Европе, например, любят ;.
df = pd.read_csv("data_semicolon.csv", sep=";")
print(df.head())
🔧 Подсказка:
- Используй параметр sep, чтобы указать правильный разделитель (;, \t, | и т.д.).
- Не угадывай вручную — открой файл в блокноте и посмотри глазами.
🧹 Пример 4: Очистка плохих данных (null, лишние пробелы)
CSV-файл часто бывает неопрятным, особенно если его делал не ты.
df = pd.read_csv("messy.csv")
# Удаляем пустые строки
df.dropna(inplace=True)
# Убираем пробелы в начале и конце строк во всех колонках
df = df.applymap(lambda x: x.strip() if isinstance(x, str) else x)
# Преобразуем строку в число (если вдруг были запятые в цене)
df["price"] = df["price"].str.replace(",", ".").astype(float)
print(df.head())
🧽 Фишки:
- dropna() — выкидывает строки с пустыми значениями.
- applymap(...) — применяет функцию ко всем ячейкам.
- astype(float) — преобразуем текст в число (полезно для расчётов).
🧠 Пример 5: Анализ таблицы с группировками и агрегацией
Допустим, у нас таблица продаж: товар, дата, сумма. Хочется понять, что продаётся лучше всего.
df = pd.read_csv("sales.csv")
# Группируем по товару и суммируем выручку
sales_by_product = df.groupby("product")["amount"].sum().sort_values(ascending=False)
print(sales_by_product)
📊 Анализ:
- groupby("product") — собираем данные по товару.
- ["amount"].sum() — суммируем продажи.
- sort_values() — сортируем от самого продаваемого.
📥 Дополнительные приёмы
✅ Сохранение в CSV:
df.to_csv("clean_data.csv", index=False, encoding="utf-8")
- index=False — не сохраняем номера строк.
- encoding="utf-8" — сохраняем в универсальной кодировке.
Супер, продолжаем! Вот дополнение к статье: продвинутые темы, с которыми часто сталкиваются в реальных проектах.
🏋️♀️ Пример 6: Работа с большими CSV-файлами (читаем по кусочкам)
Иногда CSV-файл весит как три сезона сериала в 4K. И если вы попытаетесь загрузить его целиком — можно поймать MemoryError, особенно на слабых машинах.
🔄 Решение: читать по частям (chunksize)
import pandas as pd
chunk_size = 10000 # читаем по 10 тысяч строк за раз
results = []
for chunk in pd.read_csv("big_data.csv", chunksize=chunk_size):
# Предположим, считаем среднее по колонке "amount"
mean_value = chunk["amount"].mean()
results.append(mean_value)
# Среднее значение по всем частям
overall_mean = sum(results) / len(results)
print(f"Среднее значение: {overall_mean:.2f}")
📦 Пояснения:
- chunksize — разбивает файл на части, которые читаются как мини-таблицы.
- Это позволяет не загружать всё в память.
- Отлично подходит для логов, транзакций и больших выгрузок.
🌐 Пример 7: Определение кодировки автоматически
Бывает, CSV приходит без маркировки кодировки, и угадывать наугад — это путь боли.
🔍 Решение: использовать библиотеку chardet
pip install chardet
import chardet
# Определяем кодировку
with open("unknown.csv", "rb") as f:
result = chardet.detect(f.read(10000))
print(f"Определённая кодировка: {result['encoding']}")
# Читаем с правильной кодировкой
df = pd.read_csv("unknown.csv", encoding=result["encoding"])
🧠 Фишка:
- chardet не всегда даёт 100% точность, но это лучше, чем гадать пальцем в небо.
🧪 Пример 8: Автоматическое определение разделителя
Иногда тебе присылают файл под названием data.csv, внутри которого... табуляции (\t). Или пайпы (|). Или пробелы.
📎 Решение: использовать csv.Sniffer
import csv
with open("weird.csv", "r", encoding="utf-8") as f:
sample = f.read(1024)
dialect = csv.Sniffer().sniff(sample)
df = pd.read_csv("weird.csv", sep=dialect.delimiter)
print(df.head())
🕵️ Полезно:
- csv.Sniffer() пытается угадать формат: какой разделитель, есть ли заголовки и т.д.
- Работает не всегда идеально, но часто спасает.
🧹 Пример 9: Чистим и нормализуем данные
Допустим, в таблице куча «мусора»: пропуски, дубли, непонятные значения. Всё это надо прибрать.
df = pd.read_csv("dirty_data.csv")
# Удалим дублирующиеся строки
df = df.drop_duplicates()
# Удалим строки, где в колонке "age" нет данных
df = df[df["age"].notna()]
# Заменим все значения "N/A", "нет", "пусто" на NaN
df.replace(["N/A", "нет", "пусто"], pd.NA, inplace=True)
# Заполним пропуски средним значением
df["age"] = pd.to_numeric(df["age"], errors="coerce")
df["age"].fillna(df["age"].mean(), inplace=True)
print(df.head())
🧽 Советы:
- drop_duplicates() — очистка повторов.
- replace() — заменяем мусорные значения.
- pd.to_numeric(..., errors="coerce") — всё, что не число, превращаем в NaN.
🎁 Пример 10: Сохранение данных в Excel
CSV — это, конечно, прекрасно. Но иногда заказчик говорит: «Скинь в Excel». Без паники:
df.to_excel("output.xlsx", index=False)
- Работает из коробки с openpyxl.
- Можно сохранять несколько листов или стилизовать таблицы (если очень захочется).
🧨 Чек-лист перед работой с CSV:
✅ Посмотри на файл глазами (открой в Блокноте или VS Code).
✅ Проверь кодировку.
✅ Выясни, какой разделитель.
✅ Удали или обработай пустые строки.
✅ Преобразуй данные в нужные типы (строка, число, дата).
✅ Улыбнись. Всё получится!
💡 Вопросы, которые стоит задать себе перед парсингом CSV:
🏁 Финал
CSV — это не Excel. Это вежливо оформленный хаос. И как с любым хаосом, с ним можно справиться, если знать инструменты.
pandas — мощный нож, csv — швейцарский, а вы — уже почти мастер обработки табличек.
Неважно, прилетает вам CSV из SAP, выгрузка с сайта или таблица от менеджера — теперь вы знаете, как с этим справиться.