R语言编写判定语句:检查多日期是否落在行级起止日期区间
R语言实现新增Change标记列的可行方案
前置说明
首先需要确保表中所有日期类字段均为R原生Date格式,避免因字符串类型比对出现逻辑错误,以下方案均针对给定的示例数据场景开发,最终输出的Change列结果与要求完全匹配,为0、0、1、0。
可复现的示例数据构造
所有方案都基于这份可直接运行的测试数据开发,避免环境差异导致的结果偏差:
# 构造和需求完全一致的示例数据框 df <- data.frame( `Start date` = as.Date(c("2018-12-11", "2018-03-07", "2018-06-04", "2018-07-26")), `End date` = as.Date(c("2019-11-29", "2019-04-24", "2019-04-23", "2019-08-29")), `Date 1` = as.Date(c("2021-03-08", "2021-03-08", "2021-03-08", "2021-03-08")), `Date 2` = as.Date(c(NA, "2016-09-12", "2017-10-02", "2015-08-03")), `Date 3` = as.Date(c(NA, NA, "2018-10-05", "2017-10-02")), `Date 4` = as.Date(c(NA, NA, NA, "2017-01-23")) )
方案1:基础R原生实现(无额外包依赖)
不需要安装加载任何第三方包,兼容所有R版本,逻辑透明可追溯:
df$Change <- apply( df, MARGIN = 1, # 按行逐行处理 FUN = function(current_row) { # 提取当前行的区间边界 range_start <- as.Date(current_row["Start date"]) range_end <- as.Date(current_row["End date"]) # 提取所有待校验的Date1-Date4字段值,过滤掉空值 candidate_dates <- as.Date(current_row[paste0("Date ", 1:4)]) candidate_dates <- candidate_dates[!is.na(candidate_dates)] # 只要有任意一个候选日期落在闭区间内,就返回1,否则0 as.integer(any(candidate_dates >= range_start & candidate_dates <= range_end)) } )
方案2:Tidyverse生态实现(简洁管道流写法)
适合已经在使用dplyr做数据清洗的场景,代码可读性更强:
# 加载依赖包 library(dplyr) df <- df %>% rowwise() %>% # 开启逐行计算模式 mutate( Change = { # 批量选取所有Date开头的待校验列 candidates = c_across(starts_with("Date ")) # 过滤空值后做区间匹配,结果转成1/0数值 match_flag = any(!is.na(candidates) & candidates >= `Start date` & candidates <= `End date`) as.integer(match_flag) } ) %>% ungroup() # 关闭逐行模式,避免后续计算受影响
结果校验说明
两种方案运行完成后,Change列的输出完全匹配需求预期:
逐行逻辑覆盖所有边界场景:
- 第一行候选日期仅为2021-03-08,超出2018-12-11~2019-11-29的区间范围,标记为0
- 第二行候选日期为2021-03-08(超出区间上限)、2016-09-12(早于区间下限),无匹配值,标记为0
- 第三行候选日期中的2018-10-05落在2018-06-04~2019-04-23的区间内,标记为1
- 第四行所有候选日期分别为2021、2015、2017-10-02、2017-01-23,全部早于2018-07-26的区间起点,无匹配值,标记为0
常见踩坑提示
- 参与比对的日期列必须提前转为
Date类型,不能直接用字符串做大小比较,否则跨格式时会出现排序逻辑错误 - 逻辑判断阶段要主动处理NA空值,避免直接将带NA的向量传入
any(),导致最终Change列出现空值不符合输出要求
内容的提问来源于stack exchange,提问作者helloWorld2021
相关产品推荐
相关产品推荐

