R语言按ID分组删除组内时间间隔小于5分钟的冗余行实现方法
实现方法
你之前的代码出错原因有两个:一是没有按ID分组处理,不同ID的记录时间差被错误计算;二是判断逻辑是和相邻的上一条记录比,而规则要求是和上一条被保留的记录比,当有连续多条间隔不足5分钟的记录时,就会出现判断错误。
以下提供两种可直接运行的实现方案,180个ID的规模下运行效率完全满足需求:
方案1:tidyverse套件实现(代码简洁易读)
# 加载依赖包 library(dplyr) library(purrr) library(lubridate) # 1. 数据预处理:转换时间格式、按ID+时间升序排序 df <- df %>% mutate(Timestamp = ymd_hms(Timestamp)) %>% arrange(ID, Timestamp) # 2. 定义保留逻辑判断函数 filter_func <- function(last_keep_time, current_time) { # 当前记录和上一条保留记录间隔≥5分钟则保留当前时间,否则沿用上次保留的时间 if (difftime(current_time, last_keep_time, units = "mins") >= 5) { return(current_time) } else { return(last_keep_time) } } # 3. 分组筛选符合要求的记录 df_cleaned <- df %>% group_by(ID) %>% mutate(keep_time = accumulate(Timestamp, filter_func)) %>% filter(Timestamp == keep_time) %>% # 仅保留时间匹配的记录 ungroup() %>% select(-keep_time) # 删除辅助计算列
方案2:base R实现(无需安装额外包)
# 1. 转换时间格式 df$Timestamp <- as.POSIXct(df$Timestamp, format = "%Y-%m-%d %H:%M:%S") # 2. 按ID+时间升序排序 df <- df[order(df$ID, df$Timestamp), ] # 3. 按ID拆分数据集分别处理 df_list <- split(df, df$ID) df_cleaned_list <- lapply(df_list, function(sub_df) { keep_rows <- c(1) # 同ID下最早的记录默认保留 last_keep_time <- sub_df$Timestamp[1] for (i in 2:nrow(sub_df)) { current_time <- sub_df$Timestamp[i] if (difftime(current_time, last_keep_time, units = "mins") >= 5) { keep_rows <- c(keep_rows, i) last_keep_time <- current_time } } return(sub_df[keep_rows, ]) }) # 4. 合并处理后的结果 df_cleaned <- do.call(rbind, df_cleaned_list) # 如果需要恢复原数据集的行顺序,可再加以下代码 # df_cleaned <- df_cleaned[order(df_cleaned$Row), ]
效果验证
用你提供的样例数据测试,最终保留的记录对应原行号为1、2、5、6、8、9、10,完全符合规则要求。
内容的提问来源于stack exchange,提问作者bill_scoresby
相关产品推荐
相关产品推荐

