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

如何对时间序列数据框进行多日期范围的向量化过滤?

基于日期范围数据框的向量化过滤实现

问题背景

现有时间序列数据框df1,以及存储多组日期范围的dtr数据框,需要从df1中筛选出落在dtr任意一个日期区间内的记录。手动逐个区间判断的方式扩展性差,以下是几种向量化的实现方案。

数据定义

# 时间序列数据框 df1
df1 <- structure(list(date = structure(c(18912, 18913, 18914, 18915, 
                                       18916, 18917, 18918, 18919, 
                                       18920, 18921, 18922, 18923), class = "Date"), 
                       value1 = c(1.015, NA, NA, 1.015, 1.015, 1.015, 1.015, 1.015, 
                                  1.015, 1.015, 1.015, 1.015)), 
                  row.names = c(NA, -12L), class = "data.frame")

# 日期范围数据框 dtr
dtr <- structure(list(Start = structure(c(18912, 18916, 18922), class = "Date"), 
                      End = structure(c(18914, 18918, 18923), class = "Date")), 
                 class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -3L))

向量化实现方案

方案1:用purrr映射区间判断

利用purrr的向量化映射功能,遍历dtr的所有区间,判断日期是否落在任意区间内:

library(dplyr)
library(purrr)

df1 %>%
  filter(
    pmap_lgl(dtr, ~ between(date, ..1, ..2)) %>% rowSums() > 0
  )

输出结果:

date value1
1 2021-10-12  1.015
2 2021-10-13     NA
3 2021-10-14     NA
4 2021-10-16  1.015
5 2021-10-17  1.015
6 2021-10-18  1.015
7 2021-10-22  1.015
8 2021-10-23  1.015

方案2:用fuzzyjoin模糊连接

通过模糊连接直接匹配符合区间条件的记录,最后去重:

library(fuzzyjoin)

df1 %>%
  fuzzy_inner_join(dtr, by = c("date" = "Start", "date" = "End"),
                   match_fun = list(`>=`, `<=`)) %>%
  select(date, value1) %>%
  distinct()

输出结果与方案1一致。

方案3:原生矩阵运算实现

无需额外依赖包,用outer生成匹配矩阵后判断:

df1 %>%
  filter(
    rowSums(outer(date, dtr$Start, `>=`) & outer(date, dtr$End, `<=`)) > 0
  )

输出结果与上述方案一致。

方案4:data.table非等连接

如果使用data.table,可以通过非等连接高效实现:

library(data.table)

setDT(df1)
setDT(dtr)

df1[dtr, on = .(date >= Start, date <= End), .(date = x.date, value1)]

输出结果符合要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:01:12