Ответ вслух Senior merge, join и concat обновлено

Соединение по времени в pandas

Вопрос

Есть события пользователей и таблица смены тарифов (user_id, changed_at, plan). Нужно для каждого события знать тариф пользователя на момент события. Как сделаете в pandas?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Обычный merge по userid склеит каждое событие со всеми сменами тарифа, а потом придётся выбирать нужную, это дорого. В pandas для этого есть mergeasof: pd.mergeasof(events.sortvalues("ts"), plans.sortvalues("changedat"), lefton="ts", righton="changedat", by="userid", direction="backward").

Что должно прозвучать в ответе

  • Обычный merge по user_id размножит строки на каждую смену тарифа

  • `pd.merge_asof(events, plans, left_on="ts", right_on="changed_at", by="user_id")`

  • Обе таблицы отсортированы по времени

  • `direction="backward"`: последнее значение не позже события

  • События до первой смены тарифа получат NaN: заполнить тарифом по умолчанию

  • Проверить часовые пояса и тип datetime у обеих колонок

Что могут спросить следом

  • Как сделать то же самое в SQL?
  • Что если смены тарифа приходят с опозданием?
  • Как ограничить давность найденного значения?

Разбор

Обычный merge по user_id склеит каждое событие со всеми сменами тарифа, а потом придётся выбирать нужную, это дорого. В pandas для этого есть merge_asof: pd.merge_asof(events.sort_values("ts"), plans.sort_values("changed_at"), left_on="ts", right_on="changed_at", by="user_id", direction="backward"). Для каждого события он берёт последнюю смену тарифа этого пользователя не позже события. Обе таблицы должны быть отсортированы по времени, а колонки времени одного типа и в одном часовом поясе. События до первой смены получат NaN, их заполняю стартовым тарифом. Если нужно отсечь слишком старые значения, есть параметр tolerance. В SQL то же делают через LATERAL с ORDER BY changed_at DESC LIMIT 1.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.