メモ:前処理大全 7-5「不等式条件での結合」は dplyr なら join_by() が使えるよ

少し前に改訂新版が出ましたね、前処理大全。

7-5「不等式条件での結合」は、旧版から変わっていないトピックですが、実は dplyr はこの数年の間に進化しています。 当時は非等価結合ができなかったんですが、バージョン1.1.0(2023年1月リリース)からできるようになっています。

具体的には、join_*()join_by() という指定ができるようになっていて、これを使うと全組み合わせのうち条件を満たすものだけを残して join してくれます。 例題では、reservation にある reserved_at 列が campaignstarts_at 列と ends_at 列の期間に含まれていればいいので、以下のような書き方になります。

reservation |>
  left_join(
    campaign,
    join_by(between(reserved_at, starts_at, ends_at))
  )

今回は、

を比較するパターンでしたが、区間区間を比較するような条件も書けます。

  • overlaps(): 2つの区間にオーバーラップがあるか
  • within(): 片方の区間がもう片方の区間を包含しているか

あとは、難しい概念として rolling join というのもあります。説明は省略しますが、ユーザーの行動ログの分析をしたりするときはわりとよく使う気がしますね。

こんな感じで柔軟な join_by() ですが、任意の条件を指定できるわけではありません。 たとえば、以下のように正規表現で join したくなるようなときがあったりするかもしれませんが、そういうことはできないみたいです。

dplyr 以外のやり方については、以下の記事にまとまっています(今書くならここに duckdb が入ってきそう)。 data.table ではもっと前からできたみたいです。さすがですね。

余談

Polars の場合は、issue としてはあるのでサポートしようという意志はあるみたいです。 このへんはまあ duckdb の方が小回りが利くなという印象。