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

使用时间阈值统计未来/过去NoShow事件时slider包报错求助

问题:使用slider包统计时间范围内的NoShow事件时触发排序错误

背景

此前找到类似问题的解决方案,但应用到自身数据集时运行失败并报错。

模拟数据集

df <- data.frame(Person = c('111','334','334','334','334','334','888','888','888','888','888','888','888','888'), 
                 NoShow = c(0,0,0,1,1,0,0,0,0,0,0,1,0,1), 
                 date = c('2017-03-04','2017-11-14','2018-04-26','2020-01-24','2020-01-25','2020-02-29','2018-08-09',
                          '2018-08-09','2018-04-10','2019-09-20','2020-06-30','2020-11-18','2021-08-13','2021-11-10')
)

原统计代码

library(lubridate); library(dplyr); library(slider)

### 统计未来2年的NoShow事件
df <- df %>%
  mutate(date = ymd(date)) %>%
  group_by(Person) %>%
  arrange(Person, date) %>% 
  mutate(no_shows_next2yr = slider::slide_index_dbl(
    NoShow, date, sum, .before = days(-1), .after = years(2)
  ))

### 统计过去2年的NoShow事件
df <- df %>%
  mutate(date = ymd(date)) %>%
  group_by(Person) %>%
  arrange(Person, date) %>% 
  mutate(no_shows_past2yr = slider::slide_index_dbl(
    NoShow, date, sum, .before = years(2), .after = days(-1)
  ))

报错信息

未来统计报错

Error in `mutate()`:
! Problem while computing `no_shows_next2yr = slider::slide_index_dbl(...)`.
ℹ The error occurred in group 2: Person = "334".
Caused by error in `slider::slide_index_dbl()`:
ℹ In locations: 5
! Endpoints generated by `.after` must be in ascending order.
Run `rlang::last_trace()` to see where the error occurred.
> rlang::last_trace()
<error/dplyr:::mutate_error>
Error in `mutate()`:
! Problem while computing `no_shows_next2yr = slider::slide_index_dbl(...)`.
ℹ The error occurred in group 2: Person = "334".
Caused by error in `slider::slide_index_dbl()`:
ℹ In locations: 5
! Endpoints generated by `.after` must be in ascending order.
---
Backtrace:
    ▆
 1. ├─... %>% ...
 2. ├─dplyr::mutate(...)
 3. ├─dplyr:::mutate.data.frame(...)
 4. │ └─dplyr:::mutate_cols(.data, dplyr_quosures(...), caller_env = caller_env())
 5. │   ├─base::withCallingHandlers(...)
 6. │   └─mask$eval_all_mutate(quo)
 7. └─slider::slide_index_dbl(NoShow, date, sum, .before = days(-1), .after = years(2))

过去统计报错

Error in `mutate()`:
! Problem while computing `no_shows_past2yr = slider::slide_index_dbl(...)`.
ℹ The error occurred in group 2: Person = "334".
Caused by error in `slider::slide_index_dbl()`:
ℹ In locations: 5
! Endpoints generated by `.before` must be in ascending order.
Run `rlang::last_trace()` to see where the error occurred.
> rlang::last_trace()
<error/dplyr:::mutate_error>
Error in `mutate()`:
! Problem while computing `no_shows_past2yr = slider::slide_index_dbl(...)`.
ℹ The error occurred in group 2: Person = "334".
Caused by error in `slider::slide_index_dbl()`:
ℹ In locations: 5
! Endpoints generated by `.before` must be in ascending order.
---
Backtrace:
    ▆
 1. ├─... %>% ...
 2. ├─dplyr::mutate(...)
 3. ├─dplyr:::mutate.data.frame(...)
 4. │ └─dplyr:::mutate_cols(.data, dplyr_quosures(...), caller_env = caller_env())
 5. │   ├─base::withCallingHandlers(...)
 6. │   └─mask$eval_all_mutate(quo)
 7. └─slider::slide_index_dbl(NoShow, date, sum, .before = years(2), .after = days(-1))

问题原因

报错核心是同一Person下存在重复日期的记录,slider包的slide_index_*函数要求索引(此处为date)必须能生成严格递增的窗口端点。当存在重复日期时,计算窗口边界会出现端点顺序混乱的情况,触发排序错误。

解决方案

步骤1:处理重复日期

给同一Person同一日期的记录添加微小时间差(毫秒级),确保每个日期唯一,同时不影响天级时间范围的统计逻辑。

步骤2:修正统计代码

调整窗口边界参数,用更精准的数值替代days(-1),避免日期精度导致的边界问题。

修正后的完整代码

library(lubridate); library(dplyr); library(slider)

# 预处理:转换日期并添加微秒级差异消除重复
df <- df %>%
  mutate(date = ymd(date)) %>%
  group_by(Person, date) %>%
  mutate(date = date + milliseconds(row_number())) %>% # 给同日期记录加不同毫秒数
  ungroup()

# 统计未来2年的NoShow事件(当前时间之后到2年内,不含当天)
df <- df %>%
  group_by(Person) %>%
  arrange(Person, date) %>%
  mutate(no_shows_next2yr = slider::slide_index_dbl(
    NoShow, date, sum,
    .before = -1e-9, # 精准表示当前时间之后的最小单位
    .after = years(2)
  ))

# 统计过去2年的NoShow事件(2年前到当前时间之前,不含当天)
df <- df %>%
  group_by(Person) %>%
  arrange(Person, date) %>%
  mutate(no_shows_past2yr = slider::slide_index_dbl(
    NoShow, date, sum,
    .before = years(2),
    .after = -1e-9 # 精准表示当前时间之前的最小单位
  )) %>%
  ungroup()

# 可选:将日期转回纯日期格式(去掉毫秒)
df <- df %>%
  mutate(date = as_date(date))

View(df)

说明

  • 用milliseconds(row_number())给同日期记录添加差异,既保证日期严格递增,又不会改变原日期的天级统计逻辑。
  • 用-1e-9替代days(-1),更精准地控制窗口边界,避免因日期精度问题导致的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:25:01