如何检查R语言DataFrame中日期序列连贯性及忽略NA值
问题背景
现有如下示例DataFrame(实际数据包含更多日期):
library(lubridate) df = data.frame(id = 1:5, date1 = dmy(c('01/02/2021','03/05/2022','01/03/2021','08/12/2021','01/02/2021')), date2 = dmy(c('03/02/2021','04/06/2022','03/08/2021','08/11/2022','02/05/2021')), date3 = dmy(c('04/03/2021','03/08/2022','06/09/2021','09/08/2022','03/06/2021')), date4 = dmy(c('05/08/2021','08/09/2022','09/10/2021','21/12/2022','03/07/2021')), date5 = dmy(c('09/11/2021','11/08/2022','04/11/2021','10/02/2023','04/11/2021')))
需求:检查每个id对应的所有日期是否连贯,即任意两个日期均满足前者小于后者(如date1<date2、date1<date3、date2<date3等所有组合)。
更新场景:存在NA值的情况
当DataFrame包含NA值时:
df = data.frame(id = 1:5, date1 = dmy(c('01/02/2021','03/05/2022','01/03/2021','08/12/2021','01/02/2021')), date2 = dmy(c('03/02/2021','04/06/2022','03/08/2021','08/11/2022','02/05/2021')), date3 = dmy(c('04/03/2021','03/08/2022',NA,'09/08/2022','03/06/2021')), date4 = dmy(c('05/08/2021','08/09/2022',NA,'21/12/2022','03/07/2021')), date5 = dmy(c('09/11/2021','11/08/2022','04/11/2021','10/02/2023','04/11/2021')))
应用原有方法后输出如下,其中id=3的is_coherent为NA,但实际我们希望忽略NA后判断剩余日期是否连贯:
# A tibble: 5 x 7 # Rowwise: id date1 date2 date3 date4 date5 is_coherent <int> <date> <date> <date> <date> <date> <lgl> 1 1 2021-02-01 2021-02-03 2021-03-04 2021-08-05 2021-11-09 TRUE 2 2 2022-05-03 2022-06-04 2022-08-03 2022-09-08 2022-08-11 FALSE 3 3 2021-03-01 2021-08-03 NA NA 2021-11-04 NA 4 4 2021-12-08 2022-11-08 2022-08-09 2022-12-21 2023-02-10 FALSE 5 5 2021-02-01 2021-05-02 2021-06-03 2021-07-03 2021-11-04 TRUE
核心问题:如何让R忽略NA值,仅基于非NA日期判断连贯性?
解决方案
核心逻辑:对每行的非NA日期,检查它们是否严格按顺序递增(若非NA日期严格递增,则任意两个日期都满足前者小于后者)。
方法1:使用dplyr + purrr实现
library(dplyr) library(purrr) library(lubridate) df_result <- df %>% rowwise() %>% mutate( # 提取当前行所有日期列的非NA值,保留原顺序 non_na_dates = list(c_across(starts_with("date"))[!is.na(c_across(starts_with("date")))]), # 判断连贯性:0/1个非NA日期默认连贯;多个时检查是否和排序后一致且无重复 is_coherent = case_when( length(non_na_dates) <= 1 ~ TRUE, TRUE ~ all(non_na_dates == sort(non_na_dates)) & !any(duplicated(non_na_dates)) ) ) %>% ungroup() %>% select(-non_na_dates) # 可选:移除中间辅助列 # 查看结果 print(df_result)
方法2:基础R实现(无需额外包)
# 定义判断函数 check_coherent <- function(row) { # 提取当前行的所有日期列 dates <- row[grepl("date", names(row))] # 筛选非NA值 non_na_dates <- dates[!is.na(dates)] # 逻辑判断 if (length(non_na_dates) <= 1) { return(TRUE) } else { return(all(non_na_dates == sort(non_na_dates)) & !any(duplicated(non_na_dates))) } } # 应用到DataFrame的每一行 df$is_coherent <- apply(df, 1, check_coherent) # 查看结果 print(df)
结果说明
运行上述代码后,id=3的is_coherent会返回TRUE(剩余的date1、date2、date5严格递增),其他id的结果保持准确:
- id=2:
date5早于date4,返回FALSE - id=4:
date3早于date2,返回FALSE - id=1、5:所有非NA日期严格递增,返回
TRUE
内容的提问来源于stack exchange,提问作者An116
相关产品推荐
相关产品推荐

