Как обойти проблему обработки больших файлов в Pandas, которые не помещаются в память
Что проверяют
Умеете ли вы сначала уменьшить задачу, а уже потом менять инструмент. Интервьюер ждёт порядок действий: какие колонки и типы нужны, можно ли считать по частям, когда пора уходить с Pandas. Следом часто просят посчитать среднее по группам на чанках.
Как отвечать
Идите от дешёвого к дорогому:
- читать меньше:
usecolsоставляет нужные колонки,nrowsдаёт пробу. Реальный объём показываетdf.info(memory_usage="deep"); - правильные типы: строки с малым числом значений в
category, числа понижаются черезdtypeилиpd.to_numeric(downcast=...). Главный пожиратель памяти обычно строки вobject; - чанки:
pd.read_csv(path, chunksize=500_000)возвращает итератор. Для агрегатов копите суммы и счётчики, делите в конце; - колоночный формат: один раз переложите CSV в Parquet, дальше
pd.read_parquet(path, columns=[...], filters=[...])читает только нужные колонки и группы строк.engine="pyarrow"вread_csvпарсит заметно быстрее; - DuckDB: SQL прямо по CSV и Parquet без загрузки целиком, результат в DataFrame через
.df(). Для агрегаций и джойнов на одной машине часто самый быстрый путь; - Polars: ленивый
pl.scan_parquet(...)строит план и обрабатывает данные порциями; - Dask и Spark: когда нужна параллельность на кластере и сотни гигабайт. Dask повторяет API Pandas, но не целиком.
Закончите правилом: сначала посмотрите, сколько занимают нужные колонки после приведения типов. Нередко после отбора колонок и category данные занимают в памяти в разы меньше и влезают без смены инструмента.
Где спотыкаются
Читают по чанкам, а потом склеивают их через pd.concat в один DataFrame. Памяти нужно столько же, сколько без чанков.
Считают groupby в каждом чанке и усредняют средние. При чанках разного размера это неверно, а медиану и число уникальных значений по частям так вообще не собрать.
Сразу предлагают Spark для файла на пару десятков гигабайт. Интервьюер спросит, зачем кластер, если DuckDB или Polars справятся на ноутбуке.