Половина багов в анализе случается на первой строке: при чтении файла. Неверный разделитель, потерянные ведущие нули, «NA» как пропуск, кодировка Windows-1251. На собесе это проверяют вопросами «почему у вас id стали числами» и «как прочитать файл на 20 ГБ».
CSV: главные параметры read_csv
import pandas as pd
df = pd.read_csv(
'orders.csv',
sep=';', # в русских выгрузках из Excel часто точка с запятой
decimal=',', # и запятая в дробях
encoding='cp1251', # старые выгрузки 1С и Excel; по умолчанию utf-8
dtype={'inn': 'string', 'zip': 'string'},
parse_dates=['created_at'],
usecols=['inn', 'zip', 'amount', 'created_at'],
)
- dtype для идентификаторов. ИНН, индексы, артикулы
007без явногоdtypeстанут числами, ведущие нули пропадут, а длинные номера могут превратиться во float с потерей точности. - decimal. Без
decimal=','колонка12,5прочитается строкой, иsum()склеит строки или упадёт. - usecols читает только нужные колонки: меньше памяти и быстрее.
- parse_dates сразу разбирает даты. Без него даты останутся строками.
Пропуски при чтении
По умолчанию пустая ячейка и строки вроде NA, NaN, null, N/A становятся NaN. Иногда это ломает данные: код страны Намибии NA или фамилия Null станут пропуском. Управление:
pd.read_csv(f, keep_default_na=False, na_values=[''])
Колонка целых чисел с пропуском превращается во float (1.0, NaN, 3.0). Чтобы остались целые, используйте nullable-тип: dtype={'qty': 'Int64'}.
Большие файлы
Если файл не влезает в память:
total = 0
for chunk in pd.read_csv('big.csv', chunksize=1_000_000, usecols=['amount']):
total += chunk['amount'].sum()
chunksize возвращает итератор кусков, каждый кусок обычный DataFrame. Агрегаты, которые можно сложить (сумма, число строк, минимум), считаются по кускам и объединяются. Медиану и уникальные так не посчитать в лоб: нужны другие приёмы или другой инструмент (DuckDB, Polars, Spark).
Parquet вместо CSV
df.to_parquet('orders.parquet') # нужен pyarrow
df = pd.read_parquet('orders.parquet', columns=['user', 'amount'])
Parquet колоночный и бинарный: хранит типы (даты остаются датами, category остаётся категорией), сжат, читает только нужные колонки. На тех же данных он обычно в разы меньше и быстрее CSV. Для промежуточных результатов анализа почти всегда лучше CSV.
Excel
pd.read_excel('report.xlsx', sheet_name='Продажи', skiprows=2)
pd.read_excel('report.xlsx', sheet_name=None) # словарь всех листов
Нужен пакет openpyxl. Excel медленный и капризный: объединённые ячейки, шапки в несколько строк, даты числами. Для больших данных просите выгрузку в CSV или Parquet.
SQL
from sqlalchemy import create_engine
engine = create_engine('postgresql+psycopg://user:pass@host/db')
df = pd.read_sql('SELECT user_id, amount FROM orders WHERE created_at >= %(d)s',
engine, params={'d': '2026-10-01'})
Фильтры и агрегаты выгоднее делать в базе: тащить миллион строк в pandas, чтобы потом посчитать сумму, неэффективно. Параметры передавайте через params, а не форматированием строки: это защита от SQL-инъекций.
JSON
pd.read_json читает плоские JSON. Вложенные ответы API разворачивает pd.json_normalize:
pd.json_normalize(records) # {'user': {'city': 'Казань'}} станет колонкой user.city
Запись
to_csv(path, index=False): безindex=Falseв файл уйдёт лишняя безымянная колонка индекса.- Для Excel в русской локали:
to_csv(..., sep=';', encoding='utf-8-sig'), иначе Excel покажет кракозябры.
Частые ошибки
- ID без
dtype=strпотеряли ведущие нули. - Неверный
sepилиdecimal: всё в одной колонке или числа строками. NAкак реальное значение превратилось в пропуск.- Выгрузили миллионы строк из БД ради одной суммы.
- Сохранили промежуточные данные в CSV и потеряли типы.
Что спросят на собесе
- Почему после чтения CSV пропали ведущие нули и как это исправить?
- Как прочитать файл, который не помещается в память?
- Чем Parquet лучше CSV?
- Почему колонка целых чисел стала float?
- Как безопасно передать параметры в SQL-запрос из pandas?