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

R语言递归过滤数据:移除距上一条保留记录不足7天的条目

数据清洗需求:保留间隔≥7天的记录

需求规则:移除所有距离上一条保留记录不足7天的条目(已被移除的条目不计入判断依据)。

数据示例

library(dplyr)
library(lubridate)
df = data.frame(id = c(rep(1,5), rep(2,3)),
                date = c(ymd("2022-01-01"), ymd("2022-01-03"), ymd("2022-01-05"), ymd("2022-01-09"), ymd("2022-01-20"),
                         ymd("2022-01-02"), ymd("2022-01-03"), ymd("2022-01-09"))) %>%
  arrange(id, date)

原始数据输出:

id       date
1  1 2022-01-01
2  1 2022-01-03
3  1 2022-01-05
4  1 2022-01-09
5  1 2022-01-20
6  2 2022-01-02
7  2 2022-01-03
8  2 2022-01-09

期望结果

id       date
1  1 2022-01-01
2  1 2022-01-09
3  1 2022-01-20
4  2 2022-01-02
5  2 2022-01-09

尝试的代码及问题

使用filter()和lag()函数无法满足需求,代码如下:

df %>% 
  group_by(id) %>% 
  mutate(prev = lag(date + days(7))) %>% 
  ungroup() %>% 
  filter(is.na(prev) | (date - prev >= 0))

得到的不符合预期的结果:

id       date      
1     1 2022-01-01
2     1 2022-01-20
3     2 2022-01-02

解决方案

问题核心是lag()仅能获取上一行的日期,无法跟踪上一条被保留记录的日期。需要通过累积计算或循环的方式,逐行判断当前日期是否与上一条保留日期间隔≥7天,满足则保留并更新基准日期,否则跳过。

方法1:dplyr结合purrr::accumulate实现累积判断

library(dplyr)
library(lubridate)
library(purrr)

df_cleaned <- df %>%
  group_by(id) %>%
  mutate(
    # 累积更新上一条保留的日期
    last_kept_date = accumulate(date, function(prev, curr) {
      if (curr - prev >= days(7)) curr else prev
    }, .init = first(date) - days(7)) %>% 
    tail(-1), # 移除初始化的占位值
    # 判断当前记录是否保留:第一条必留,或与上一条保留日期间隔≥7天
    keep = row_number() == 1 | date >= last_kept_date + days(7)
  ) %>%
  filter(keep) %>%
  select(id, date) %>%
  ungroup()

print(df_cleaned)

方法2:自定义循环函数(逻辑更直观)

clean_dates <- function(group_df) {
  kept_indices <- c(1) # 第一条记录默认保留
  last_kept_date <- group_df$date[1]
  
  for (i in 2:nrow(group_df)) {
    if (group_df$date[i] - last_kept_date >= days(7)) {
      kept_indices <- c(kept_indices, i)
      last_kept_date <- group_df$date[i]
    }
  }
  
  return(group_df[kept_indices, ])
}

df_cleaned <- df %>%
  group_by(id) %>%
  group_modify(~clean_dates(.x)) %>%
  ungroup()

print(df_cleaned)

两种方法均可得到预期结果:

# A tibble: 5 × 2
     id date      
  <dbl> <date>    
1     1 2022-01-01
2     1 2022-01-09
3     1 2022-01-20
4     2 2022-01-02
5     2 2022-01-09

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:15:36