pd.merge_asof() — join по ближайшему ключу для time-series

merge_asof делает «as-of» join: для каждой строки левой таблицы берёт ближайшую по ключу строку правой (по умолчанию — последнюю не позже). Аналитику это нужно, чтобы приклеить к событию актуальный на тот момент курс, цену, тариф или статус, когда таймстемпы не совпадают ровно. По сути это left join, где равенство заменено на «ближайшее значение».

Синтаксис

pd.merge_asof(left, right, on=…, by=…, direction='backward', tolerance=…)

Примеры использования

Пример 1: Приклеить к заказу курс на момент заказа

prices = pd.DataFrame({'ts': pd.to_datetime(['2026-01-01 10:00','2026-01-01 10:05']),
                       'rate': [90.1, 90.4]})
orders = pd.DataFrame({'order_id': [1, 2],
                       'ts': pd.to_datetime(['2026-01-01 10:03','2026-01-01 10:07']),
                       'amount': [100, 200]})
pd.merge_asof(orders, prices, on='ts')

Результат:

   order_id                  ts  amount  rate
0         1 2026-01-01 10:03:00     100  90.1
1         2 2026-01-01 10:07:00     200  90.4

Пример 2: tolerance: если ближе порога нет — NaN

pd.merge_asof(orders, prices, on='ts',
              tolerance=pd.Timedelta('2min'))

Результат:

   order_id                  ts  amount  rate
0         1 2026-01-01 10:03:00     100   NaN
1         2 2026-01-01 10:07:00     200  90.4
Порешать Python-задачи в тренажёре →

Типичная ошибка

Обе таблицы должны быть отсортированы по ключу on, иначе ValueError. Ключи должны быть одного типа (datetime к datetime, int к int). direction меняет логику: 'backward' (по умолчанию) — не позже, 'forward' — не раньше, 'nearest' — ближайшая в любую сторону; для точного совпадения категорий добавляй by.

Где спрашивают на собеседовании

Классика для time-series: сматчить сделки с котировками, заказы с ценами/курсами, события с последним известным снапшотом. Часто спрашивают на собеседовании как альтернативу тяжёлому join + фильтрации по времени.

FAQ: частые вопросы про merge_asof

Чем merge_asof отличается от обычного merge?

merge джойнит по точному равенству ключей, а merge_asof — по ближайшему значению. Это всегда left join: каждой строке left подбирается одна строка right, ближайшая по ключу в заданном направлении. Если подходящей нет, поля из right становятся NaN.

Зачем параметр by?

by задаёт колонки, по которым нужно точное совпадение, прежде чем искать ближайший ключ. Например, by='channel' сматчит цену по тому же каналу, а on='ts' уже выберет ближайший момент внутри канала. Это аналог группового as-of join.

Почему получаю ошибку про сортировку?

merge_asof требует, чтобы обе таблицы были отсортированы по колонке on по возрастанию. Отсортируй их через sort_values('ts') перед вызовом. Если используешь by, внутри каждой группы порядок по ключу тоже должен быть возрастающим.

Задачи в тренажёре по теме

Вопросы с собеседований по теме

Смежные темы Python

Pandas merge / join · Pandas: временные ряды

Другие функции pandas

merge · to_datetime · concat · rolling · resample · shift

Открыть Python-тренажёр (556 задач) →