Ответ
При ошибке памяти при слиянии в Pandas я действую по следующему чек-листу, начиная с самых вероятных причин:
1. Анализ объема данных:
# Оцениваю реальный объем памяти, занимаемый DataFrame
print(f"df1: {df1.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
print(f"df2: {df2.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
# Смотрю размеры таблиц
print(f"df1 shape: {df1.shape}, df2 shape: {df2.shape}")
Если суммарный объем близок к доступной оперативной памяти — проблема очевидна.
2. Оптимизация типов данных:
Часто в сырых данных используются неоптимальные типы, например, int64 или object для категориальных признаков.
# Привожу типы к более эффективным
df['category_col'] = df['category_col'].astype('category')
df['int_col'] = pd.to_numeric(df['int_col'], downcast='integer')
df['float_col'] = pd.to_numeric(df['float_col'], downcast='float')
3. Выбор стратегии слияния:
innerjoin создает наименьшую результирующую таблицу.- Если нужен
outerjoin, иногда эффективнее сделать дваinnerзапроса и затем конкатенировать результаты.
4. Проверка ключей слияния: Дубликаты в ключах могут взрывным образом увеличивать размер результата (декартово произведение).
# Проверяю на дубликаты ключей
print(f"Дубликаты в df1['key']: {df1['key'].duplicated().sum()}")
print(f"Дубликаты в df2['key']: {df2['key'].duplicated().sum()}")
5. Альтернативные подходы:
- Итеративная обработка: Разбиваю одну из таблиц на чанки и делаю merge по частям.
- Использование Dask: Если данные не помещаются в память, перехожу на библиотеку Dask для работы с ними на диске или в распределенной памяти.
- Переход к СУБД: Для регулярных операций с большими объемами данных правильным решением является использование базы данных (например, PostgreSQL) и выполнение JOIN средствами SQL.