Короткий ответ
Типичные приёмы — предварительно отсортировать или проиндексировать данные по ключу объединения/группировки, уменьшить типы данных (category, меньшая разрядность чисел), отфильтровать и выбрать только нужные столбцы до тяжёлой операции, и избегать повторных merge/groupby там, где можно объединить логику в один проход.
Как это работает подробнее
merge и groupby внутри используют хеширование или сортировку по ключу; если ключ имеет тип object (строка) вместо category или числового типа, сравнение и хеширование происходит медленнее; выбор только нужных столбцов (usecols при чтении, или df[['a','b']] до операции) снижает объём данных, которые нужно переставлять в памяти.
Пример кода
Пример на Python
import pandas as pd
import time
df = pd.DataFrame({'key': (['A', 'B'] * 500000), 'value': range(1000000)})
df['key_cat'] = df['key'].astype('category')
start = time.time()
df.groupby('key')['value'].sum()
t_object = time.time() - start
start = time.time()
df.groupby('key_cat')['value'].sum()
t_category = time.time() - start
print(t_object, t_category)Что использовать на практике
- На практике. перед тяжёлым merge полезно сначала отфильтровать обе таблицы до нужного подмножества строк (например, только за нужный период), а не объединять всё и фильтровать потом; для повторяющихся по одному и тому же ключу группировок стоит задуматься об установке ключа как индекса (set_index) заранее, что может ускорить последующие операции доступа.
- Проверка. t_category должен быть не больше, а на больших и разнообразных по кардинальности данных обычно заметно меньше t_object, что подтверждает выигрыш от использования category для ключа группировки.
Подводные камни
- Частые ошибки. оптимизируют типы данных после тяжёлой операции, а не перед ней, теряя весь потенциальный выигрыш; выполняют несколько отдельных groupby по одному и тому же ключу для разных метрик вместо одного groupby с agg по словарю, умножая время выполнения без необходимости.