基于多条件压缩合并R语言DataFrame中的行
解决R中按玩家组压缩连续胜负streak并计算得分均值的高效方案
核心思路:先给每30行数据标记玩家组ID以隔离跨组streak,再在组内识别连续相同胜负的记录段,最后按组+streak段聚合计算得分均值。以下是两种适配不同场景的高效实现:
方法1:使用data.table(大数据量首选,性能最优)
data.table针对超大数据集做了内存优化,避免冗余复制,处理速度远快于传统tidyverse工具。
# 加载包 library(data.table) # 构造示例数据(60行=2组玩家,每组30行) set.seed(123) df <- data.table( win = sample(c(0,1), 60, replace = TRUE), sound = sample(1:10, 60, replace = TRUE) ) # 1. 生成玩家组ID(每30行一组) df[, group_id := floor((.I - 1)/30) + 1] # 2. 在每个组内标记连续胜负的streak ID df[, streak_id := rleid(win), by = group_id] # 3. 按组+streak聚合,计算得分均值 result_dt <- df[, .( win = first(win), # 同一streak内win值一致,取任意值均可 sound_mean = mean(sound) ), by = .(group_id, streak_id)] # 查看结果 head(result_dt)
关键细节
.I是data.table内置的行号变量,生成组ID的逻辑高效且无额外计算开销rleid()是专门用于快速识别连续相同值的函数,比手动判断前后值的方法快数倍
方法2:使用dplyr(语法直观,适配tidyverse工作流)
如果习惯tidyverse语法,可采用此方案,数据量不大时性能足够。
# 加载包 library(dplyr) # 构造示例数据 set.seed(123) df <- tibble( win = sample(c(0,1), 60, replace = TRUE), sound = sample(1:10, 60, replace = TRUE) ) # 1. 生成玩家组ID df <- df %>% mutate(group_id = floor((row_number() - 1)/30) + 1) # 2. 在每个组内标记streak ID df <- df %>% group_by(group_id) %>% mutate(streak_id = cumsum(win != lag(win, default = first(win)))) %>% ungroup() # 3. 聚合计算 result_dplyr <- df %>% group_by(group_id, streak_id) %>% summarise( win = first(win), sound_mean = mean(sound), .groups = "drop" # 清除分组状态,避免后续操作干扰 ) # 查看结果 head(result_dplyr)
关键注意事项
- 两种方案都严格通过
group_id限制streak识别范围,彻底避免跨组误判 - 若数据集规模达到千万级,优先选择data.table方案,内存占用和处理速度优势明显
内容的提问来源于stack exchange,提问作者grace.cutler
相关产品推荐
相关产品推荐

