Как работать с большим датасетом в pandas
Когда pandas не справляется
Pandas работает в памяти. Если датасет больше RAM (16–32 Gb обычно) — beda:
- MemoryError.
- Тормозит весь компьютер.
- Простой query занимает 30 минут.
Решение: или уменьшить датасет, или использовать другой инструмент.
1. Используйте dtype
По умолчанию pandas грузит числа как int64 / float64 — 8 bytes на значение. Часто избыточно.
# До
df = pd.read_csv('big.csv')
df.memory_usage(deep=True).sum() / 1024**2 # 1500 MB
# После
dtypes = {
'user_id': 'int32', # 4B вместо 8B
'amount': 'float32', # 4B вместо 8B
'status': 'category', # 1B вместо ~50B на строку
'is_active': 'bool', # 1B
}
df = pd.read_csv('big.csv', dtype=dtypes)
df.memory_usage(deep=True).sum() / 1024**2 # 400 MB → 4x экономияcategory — для столбцов с малым числом уникальных значений (страна, статус).
2. Прочитать только нужные колонки
# Все 50 столбцов
df = pd.read_csv('big.csv')
# Только 5 нужных
df = pd.read_csv('big.csv', usecols=['user_id', 'date', 'amount', 'status', 'category'])10x экономия памяти на wide-таблицах.
3. Chunksize для обработки
Если данных больше памяти — читайте по частям:
chunk_iter = pd.read_csv('big.csv', chunksize=100_000)
results = []
for chunk in chunk_iter:
# Обработка одного chunk
result = chunk.groupby('user_id')['amount'].sum().reset_index()
results.append(result)
# Объединить
final = pd.concat(results).groupby('user_id')['amount'].sum().reset_index()Обрабатываем 10 GB при 1 GB RAM.
4. Parquet вместо CSV
# CSV: медленно, без типов
df.to_csv('data.csv') # 5 GB
df = pd.read_csv('data.csv') # 60 секунд
# Parquet: быстро, типы сохраняются
df.to_parquet('data.parquet') # 2 GB (сжатие)
df = pd.read_parquet('data.parquet') # 10 секундДополнительно: parquet поддерживает read только нужных колонок.
Тренироваться на таких вопросах можно в Telegram-боте Карьерник — там 1500+ задач с реальных собесов с разборами.
5. Фильтр перед загрузкой (Parquet)
import pyarrow.parquet as pq
# Только строки, удовлетворяющие условию
table = pq.read_table('data.parquet', filters=[('country', '=', 'RU')])
df = table.to_pandas()Не грузим лишнее в память.
6. Векторизация вместо apply
# Медленно
df['x2'] = df['x'].apply(lambda v: v ** 2)
# Быстрее в 100x
df['x2'] = df['x'] ** 2
# Или через NumPy
import numpy as np
df['log_x'] = np.log(df['x'])apply с Python-функцией — последнее средство.
7. Бери SQL вместо pandas
Часто проще предагрегировать в БД, потом загрузить в pandas:
# ❌ Медленно
df = pd.read_sql('SELECT * FROM events', conn) # 50M строк
agg = df.groupby('date')['user_id'].nunique()
# ✅ Быстрее
df = pd.read_sql("""
SELECT date, COUNT(DISTINCT user_id) AS dau
FROM events GROUP BY 1
""", conn) # 365 строкClickHouse / BigQuery считают агрегаты в распределённой системе намного быстрее pandas.
8. Polars вместо pandas
Polars — современная альтернатива pandas, работает в 5–30x быстрее на больших данных.
import polars as pl
df = pl.read_csv('big.csv')
agg = df.group_by('user_id').agg(pl.col('amount').sum())Синтаксис похож на pandas, переход — за пару дней.
Когда Polars: данные 1–100 GB, нужна скорость.
9. Dask для очень больших данных
Dask — pandas API + распределённые вычисления.
import dask.dataframe as dd
df = dd.read_csv('big_*.csv') # читает много файлов
result = df.groupby('user_id')['amount'].sum().compute()Когда: данные 100 GB+, нужно обрабатывать на кластере.
10. Используйте SQL DB в качестве storage
Если данные уже в БД — обрабатывайте там, не выгружайте в pandas:
# ❌ Выгрузить → обработать → загрузить обратно
df = pd.read_sql('SELECT * FROM events', conn)
df['hour'] = df['created_at'].dt.hour
df.to_sql('events_hourly', conn)
# ✅ Сделать всё в SQL
conn.execute("""
CREATE TABLE events_hourly AS
SELECT *, EXTRACT(HOUR FROM created_at) AS hour FROM events
""")К слову, набить руку на таких кейсах удобно через тренажёр в Telegram — разбирайте по 10 вопросов в день, через 2 недели тема становится рефлексом.
Порядок действий при memory error
- Уменьшить колонки —
usecols. - Уменьшить типы —
dtypes. - Chunksize для batch-обработки.
- Parquet вместо CSV.
- Pre-aggregate в SQL.
- Polars / Dask если ничего не помогло.
Бенчмарк (примерно)
Для 10 Gb CSV → загрузить и сделать groupby:
| Инструмент | Время | RAM |
|---|---|---|
| pandas (без оптимизации) | 5 мин или OOM | 30 GB |
| pandas + dtypes | 2 мин | 12 GB |
| pandas + chunksize | 3 мин | 2 GB |
| Polars | 30 сек | 8 GB |
| Dask | 1 мин | 4 GB (multi-core) |
| ClickHouse | 5 сек | мало |
Лайфхак: pandas memory inspector
df.info(memory_usage='deep')
# Какая колонка занимает много
df.memory_usage(deep=True).sort_values(ascending=False)Читайте также
FAQ
Когда переключаться с pandas?
Когда данные >1–10 GB или операции >5 минут.
pandas или Polars?
Pandas — стандарт, больше material. Polars — современнее, быстрее. Учить оба.
Dask vs Spark?
Dask — Python-friendly, для дата-сайентистов. Spark — production-grade, для дата-инженеров.
Что делать, если данные 100 GB?
- Pre-aggregate в БД. 2) Если обработка нужна — Dask / Spark на кластере. 3) Polars если влезает на RAM сервера.