如何对时间序列数据框进行多日期范围的向量化过滤?
基于日期范围数据框的向量化过滤实现
问题背景
现有时间序列数据框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--
相关产品推荐
相关产品推荐

