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

在R中合并连续action为"o"的重复记录并保留指定时间值

在R中合并用户连续的action="o"记录

针对你提出的需求——合并同一user_id下连续的action="o"记录(保留第一条的start_time和最后一条的end_time,其他action保持原状),以下是两种高效的实现方案:

准备示例数据

首先把你提供的示例数据转换成R可处理的数据结构:

# 先安装需要的包:install.packages("tidyverse") 或 install.packages("data.table")
library(tidyverse)
# 或者用data.table:library(data.table)

# 构建示例数据集
df <- tibble(
  user_id = c("11", "11", "11", "11", "11", "11", "11", "22", "22", "22", "22", "22"),
  action = c("o", "o", "o", "v", "v", "o", "o", "o", "o", "v", "o", "z"),
  start_time = c("23:25:27", "23:25:28", "23:25:48", "23:25:49", "23:25:49", "23:28:24", "00:10:48", "00:11:52", "00:22:32", "00:22:42", "00:22:42", "00:22:42"),
  end_time = c("23:25:49", "23:25:28", "23:26:50", "23:25:49", "23:25:50", "00:22:33", "00:23:44", "00:22:33", "00:27:44", "00:22:42", "00:22:42", "00:22:43")
)

方案一:使用dplyr(tidyverse生态)

核心思路是给连续的action="o"记录打上同一分组标签,再按标签聚合:

df_merged <- df %>%
  # 按user_id分组,确保只处理同一用户内的连续记录
  group_by(user_id) %>%
  # 创建分组标识:当当前行不是"o",或者当前是"o"但前一行不是"o"时,开启新分组
  mutate(
    group_tag = cumsum(
      action != "o" | 
        (action == "o" & lag(action, default = "") != "o")
    )
  ) %>%
  # 按user_id、group_tag、action分组,聚合时间字段
  group_by(user_id, group_tag, action) %>%
  summarise(
    start_time = first(start_time),  # 取分组内第一条的start_time
    end_time = last(end_time),       # 取分组内最后一条的end_time
    .groups = "drop"  # 取消分组,返回普通数据框
  ) %>%
  select(-group_tag)  # 移除临时分组标签列

# 查看结果
print(df_merged, n = Inf)

执行后会得到你期望的输出:

# A tibble: 8 × 4
  user_id action start_time end_time
  <chr>   <chr>  <chr>      <chr>   
1 11      o      23:25:27   23:26:50
2 11      v      23:25:49   23:25:49
3 11      v      23:25:49   23:25:50
4 11      o      23:28:24   00:23:44
5 22      o      00:11:52   00:27:44
6 22      v      00:22:42   00:22:42
7 22      o      00:22:42   00:22:42
8 22      z      00:22:42   00:22:43

方案二:使用data.table(适合大型数据集)

如果你的数据集非常大,data.table的处理速度会更有优势,它的rleid函数可以快速生成连续分组的标识:

library(data.table)

# 转换为data.table格式
setDT(df)

# 分组聚合
df_merged <- df[, 
  # 对每个分组,取第一条start_time和最后一条end_time
  .(start_time = first(start_time), end_time = last(end_time)),
  # 分组依据:user_id、action,以及连续"o"的分组标识
  by = .(user_id, action, grp = rleid(action == "o"))
][, grp := NULL]  # 删除临时分组列

# 查看结果
print(df_merged)

这个方案的输出和上面完全一致,而且对于百万级以上的大型数据集,性能会显著优于dplyr。

注意事项

  • 如果你的start_time和end_time是时间类型(比如POSIXct),上述代码不需要任何修改,first()和last()函数依然有效。
  • 如果数据原本没有按时间排序,建议先在分组前添加arrange(start_time)确保记录是按时间顺序处理的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:18:38