You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于数据范围更高效地为事件分配对应值?

高效匹配事件日期与任期区间的向量化方法

我有一批带特定日期的事件,需要根据事件日期所属的任期区间给事件添加对应的领导人信息。目前用case_when写的代码虽然能跑,但扩展性很差,想知道有没有向量化的处理方式。

代表性数据

events
#>   event_name event_date
#> 1    event a 2012-05-23
#> 2    event b 2018-03-12
#> 3    event c 2019-08-17
#> 4    event d 2022-01-03

leader_tenure
#>    leader      start        end
#> 1 Manning 2012-04-09 2017-12-30
#> 2    Hale 2017-12-30 2019-11-09
#> 3 Whitney 2019-11-10 2022-05-30

现有低效且扩展性差的代码

library(dplyr)
library(lubridate)

events <- data.frame(
  event_name = c("event a", "event b", "event c", "event d"),
  event_date = ymd(c("2012-05-23", "2018-03-12", "2019-08-17", "2022-01-03"))
)

leader_tenure <- data.frame(
  leader = c("Manning", "Hale", "Whitney"),
  start = ymd(c("2012-04-09", "2017-12-30", "2019-11-10")),
  end = ymd(c("2017-12-30", "2019-11-09", "2022-05-30"))
)

events |>
  mutate(
    leader = case_when(
      event_date %within% interval(ymd("2012-04-09"), ymd("2017-12-30")) ~ "Manning",
      event_date %within% interval(ymd("2017-12-30"), ymd("2019-11-09")) ~ "Hale",
      event_date %within% interval(ymd("2019-11-10"), ymd("2022-05-30")) ~ "Whitney"
    )
  )
#>   event_name event_date  leader
#> 1    event a 2012-05-23 Manning
#> 2    event b 2018-03-12    Hale
#> 3    event c 2019-08-17    Hale
#> 4    event d 2022-01-03 Whitney

几种高效向量化解决方案

方法1:用fuzzyjoin包做区间匹配

不需要手动编写每个区间条件,新增领导人时直接更新leader_tenure数据框即可,扩展性拉满:

library(fuzzyjoin)

events |>
  fuzzy_left_join(
    leader_tenure,
    by = c("event_date" = "start", "event_date" = "end"),
    match_fun = list(`>=`, `<`) # 匹配逻辑:event_date在[start, end)区间内
  ) |>
  select(event_name, event_date, leader)

如果需要包含区间结束日期,把match_fun里的<改成<=即可。

方法2:dplyr结合rowwise简洁实现

不用额外装包,通过逐行匹配区间实现:

events |>
  rowwise() |>
  mutate(
    leader = leader_tenure$leader[which(event_date >= leader_tenure$start & event_date < leader_tenure$end)]
  ) |>
  ungroup()

方法3:完全向量化的findInterval(性能最优)

利用findInterval快速定位日期所属区间,适合大数据量场景,前提是leader_tenure的start日期是升序排列的:

events |>
  mutate(
    leader = leader_tenure$leader[findInterval(event_date, leader_tenure$start)]
  )

内容的提问来源于stack exchange,提问作者short_stack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 14:22:16