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

如何为每个ID标记当日最后报告(含午夜后提交的记录)

问题描述

我有如下结构的tibble数据:

# 数据预览
A tibble: 30 x 4
       id index   day time    
    <dbl> <int> <int> <chr>   
 1 238686     1     1 11:53:33
 2 238686     2     1 17:45:27
 3 238686     3     1 21:12:36
 4 238686     4     2 00:32:36
 5 238686     5     2 11:07:08
 6 238686     6     2 14:43:41
 7 238686     7     2 20:50:29
 8 238686     8     2 23:22:33
 9 238686     9     3 12:05:53
10 238686    10     3 14:48:50

字段说明:

  • id:参与者ID,每位参与者在10天研究期内每日提交多份报告
  • index:参与者在整个研究中的报告连续编号
  • day:研究天数
  • time:报告提交时间

我需要新增last变量,标记每个参与者当日的最后一份报告。之前用以下代码实现:

ex_data <- ex_data |>
     mutate(last=as.integer(max(index) == index), .by = c(id, day))

但发现部分参与者的当日最后报告是在午夜后提交的(比如研究day2的00:32:36实际属于研究day1的最后报告)。我已经用以下代码标记了午夜时段(00:00:00-03:00:00)的记录:

ex_data$time2<-as.hms(ex_data$time)

ex_data <- ex_data |>
mutate(nighttime = if_else(time2 >= parse_hms("00:00:00") & time2 < parse_hms("03:00:01"), 1, 0))

现在需要调整逻辑,创建last变量,同时覆盖午夜前和午夜后提交的当日最后报告,期望结果示例如下:

id     index   day time       last  
  238686     1     1  11:53:33   0
  238686     2     1  17:45:27   0
  238686     3     1  21:12:36   0
  238686     4     2  00:32:36   1
  238686     5     2  11:07:08   0
  238686     6     2  14:43:41   0
  238686     7     2  20:50:29   0
  238686     8     2  23:22:33   1
  238686     9     3  12:05:53   0

完整数据结构:

ex_data<-
structure(list(id = c(238686, 238686, 238686, 238686, 238686, 
238686, 238686, 238686, 238686, 238686, 238686, 238686, 238686, 
238686, 238686, 238686, 238686, 238686, 238686, 238686, 238686, 
238686, 238686, 238686, 238686, 238686, 238686, 238686, 238686, 
238686, 238686, 238686, 238686, 238686, 238686, 238686, 238686, 
239297, 239297, 239297), index = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 
8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 
21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L, 
34L, 35L, 36L, 37L, 1L, 2L, 3L), day = c(1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 6L, 6L, 6L, 
6L, 7L, 7L, 7L, 7L, 7L, 7L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 10L, 
10L, 1L, 1L, 1L), time = c("11:53:33", "17:45:27", "21:12:36", 
"00:32:36", "11:07:08", "14:43:41", "20:50:29", "23:22:33", "12:05:53", 
"14:48:50", "21:15:33", "12:09:46", "14:27:06", "18:01:24", "20:56:40", 
"23:17:18", "11:19:02", "17:32:18", "00:05:52", "11:45:11", "18:10:10", 
"20:08:09", "00:30:00", "11:17:36", "14:29:43", "18:12:06", "20:54:48", 
"23:20:32", "11:16:00", "17:26:45", "11:45:13", "14:30:26", "18:31:49", 
"20:31:42", "23:47:41", "14:16:07", "23:55:13", "11:16:34", "12:01:56", 
"14:33:38")), row.names = c(NA, -40L), class = c("tbl_df", "tbl", 
"data.frame"))
解决方案

核心思路是:先构建逻辑日期(把00:00-03:00的报告归为前一个研究日),再基于逻辑日期标记每个参与者的当日最后报告。

完整代码

library(dplyr)
library(hms)

ex_data <- ex_data |>
  # 转换时间为hms格式
  mutate(time2 = as.hms(time)) |>
  # 构建逻辑日:00:00-03:00的报告归为前一天
  mutate(logic_day = if_else(time2 < parse_hms("03:00:00"), day - 1, day), .by = id) |>
  # 标记每个逻辑日的最后报告
  mutate(last = as.integer(index == max(index)), .by = c(id, logic_day)) |>
  # 可选:移除中间变量
  select(-time2, -logic_day)

验证结果

运行代码后,查看目标片段:

ex_data |> slice(1:9)

输出结果与期望一致:

# A tibble: 9 × 5
      id index   day time     last
   <dbl> <int> <int> <chr>   <int>
1 238686     1     1 11:53:33     0
2 238686     2     1 17:45:27     0
3 238686     3     1 21:12:36     0
4 238686     4     2 00:32:36     1
5 238686     5     2 11:07:08     0
6 238686     6     2 14:43:41     0
7 238686     7     2 20:50:29     0
8 238686     8     2 23:22:33     1
9 238686     9     3 12:05:53     0

补充说明

  • 如果研究日起始时间不是00:00,只需调整logic_day的判断条件即可。
  • 代码中使用的.by参数需要dplyr 1.1.0及以上版本支持,若版本较低,可替换为group_by(id, logic_day)后执行mutate,最后调用ungroup()取消分组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:44:53