在R中匹配目标日期至DataFrame对应行(替代between函数方案)
解决方案:匹配目标日期对应的DataFrame行
示例数据定义
首先构造可复现的示例数据:
# 构造DataFrame mydf <- data.frame( country = c("CHI", "ENG", "GER", "FRA"), startDate = as.Date(c("2022-12-29", "2023-01-01", "2023-01-02", "2023-01-30")), endDate = as.Date(c("2023-01-08", "2023-01-08", "2023-01-08", "2023-02-05")), weather = c("Rain", "Cloud", "Cloud", "Dry") ) # 目标日期列表 datestodo <- as.Date(c("2023-02-03", "2023-02-04"))
问题说明
你之前用between(datestodo, mydf$startDate, mydf$endDate)失效的原因是向量长度不匹配:datestodo是长度2的向量,startDate/endDate是长度4的列向量,R的循环规则会错位匹配,无法实现「检查任意目标日期是否落在某一行的区间内」的需求。
可行实现方案
方案1:Base R 逐行匹配(apply)
对每一行检查是否存在目标日期落在区间内,只要有一个满足就保留该行:
# 逐行判断是否有匹配的目标日期 match_rows <- apply(mydf, 1, function(row) { any(datestodo >= as.Date(row["startDate"]) & datestodo <= as.Date(row["endDate"])) }) # 提取匹配结果 result <- mydf[match_rows, ] print(result)
方案2:Base R 向量运算+which
通过外循环生成所有日期与行的匹配矩阵,筛选出至少有一个匹配的行:
# 生成所有目标日期与每行区间的匹配矩阵 matches <- outer(datestodo, seq(nrow(mydf)), function(d, i) { d >= mydf$startDate[i] & d <= mydf$endDate[i] }) # 获取有匹配的行索引 row_indices <- which(colSums(matches) > 0) # 提取结果 result <- mydf[row_indices, ] print(result)
方案3:dplyr 管道式实现(tidyverse风格)
如果习惯使用tidyverse工具,可以用rowwise或map2_lgl实现:
library(dplyr) # 方法1:rowwise逐行判断 result <- mydf %>% rowwise() %>% filter(any(datestodo >= startDate & datestodo <= endDate)) %>% ungroup() print(result) # 方法2:用purrr的map2_lgl批量判断 library(purrr) result <- mydf %>% mutate(has_match = map2_lgl(startDate, endDate, ~any(datestodo >= .x & datestodo <= .y))) %>% filter(has_match) %>% select(-has_match) print(result)
以上方案均会返回预期的FRA对应行。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

