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

R语言使用lag函数时,如何跳过与当前行日期相同的历史行?

问题

现有包含Person、NoShow和date列的数据框:

Person NoShow       date
1    334      1 2019-07-07
2    334      1 2019-10-11
3    334      1 2020-07-07
4    334      1 2021-01-04
5    999      1 2021-06-03
6    999      1 2022-04-17
7    999      1 2022-05-03
8    999      0 2022-05-03

创建该数据框的代码:

df <- data.frame(Person = c('334','334','334','334','999','999','999','999'), 
                 NoShow = c(1,1,1,1,1,1,1,0), 
                 date = c('2019-07-07','2019-10-11','2020-07-07','2021-01-04','2021-06-03','2022-04-17','2022-05-03','2022-05-03')
)

需要生成三个新列:

  • prior_noshow:用户是否有过早于当前行日期的历史失约记录
  • prior_noshow_f:用户早于当前行日期的历史失约次数
  • last_noshow:用户最近一次早于当前行日期的失约日期

原代码运行后,第8行的prior_noshow_f为3、last_noshow为2022-05-03,不符合需求——因为第7行和第8行日期相同,不应计入历史统计,期望第8行的prior_noshow_f为2、last_noshow为2022-04-17。

解决方案

核心思路是按用户分组后,针对每行单独筛选日期更早的历史失约记录,而非简单使用累计求和或滞后函数。

修改后的代码如下:

library(tidyverse)

df <- df %>%
  # 转换日期格式,确保比较逻辑准确
  mutate(date = as.Date(date)) %>%
  group_by(Person) %>%
  mutate(
    # 统计当前行之前、日期更早的失约次数
    prior_noshow_f = map_dbl(row_number(), ~ sum(NoShow[1:(.x-1)][date[1:(.x-1)] < date[.x]])),
    # 判断是否存在符合条件的历史失约
    prior_noshow = ifelse(prior_noshow_f > 0, 1, NA),
    # 获取最近一次早于当前日期的失约日期
    last_noshow = map_chr(row_number(), ~ {
      valid_dates = date[1:(.x-1)][NoShow[1:(.x-1)] == 1 & date[1:(.x-1)] < date[.x]]
      if (length(valid_dates) > 0) max(valid_dates) else NA_character_
    })
  ) %>%
  # 转回原字符格式(可选操作)
  mutate(date = as.character(date),
         last_noshow = as.character(last_noshow)) %>%
  ungroup()

代码说明

  1. 先将date转为Date类型,避免字符格式导致的日期比较错误;
  2. prior_noshow_f:通过map_dbl遍历每行,精准筛选当前行之前、日期更早且NoShow=1的记录并计数;
  3. prior_noshow:基于失约次数判断是否存在有效历史失约;
  4. last_noshow:筛选当前行之前的有效失约日期,取最大值即为最近一次的失约日期,无有效记录则返回NA;
  5. 最后将日期转回字符格式,保持与原数据格式一致。

运行结果

Person NoShow date       prior_noshow_f prior_noshow last_noshow
  <chr>   <dbl> <chr>                <dbl>        <dbl> <chr>      
1 334         1 2019-07-07               0           NA NA         
2 334         1 2019-10-11               1            1 2019-07-07 
3 334         1 2020-07-07               2            1 2019-10-11 
4 334         1 2021-01-04               3            1 2020-07-07 
5 999         1 2021-06-03               0           NA NA         
6 999         1 2022-04-17               1            1 2021-06-03 
7 999         1 2022-05-03               2            1 2022-04-17 
8 999         0 2022-05-03               2            1 2022-04-17

可见第8行的prior_noshow_f为2,last_noshow为2022-04-17,完全符合需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:58:57