如何按分组聚合特定阈值并保留全部ShortName值?
解决dplyr处理中保留所有ShortName并生成完整Doses分组的问题
问题分析
原代码中使用filter(StrawsReleased >= 1000)会直接过滤掉累计值未达1000的行,导致这类ShortName完全从结果中消失,无法满足“保留所有ShortName值”的需求。直接移除filter则会引入不需要的Doses=0分组,不符合预期输出格式。
解决方案
通过生成所有ShortName与目标Doses的完整组合,再匹配每个分组的首次达标日期,既保留所有ShortName,又能准确获取各Doses的最早DiasColeta。
完整处理代码
library(dplyr) library(tidyr) # 计算累计吸管数和对应的Dose等级 processed_data <- ordered_data %>% mutate( CumStraws = cumsum(StrawsReleased), DoseLevel = case_when( CumStraws >= 5000 ~ 3, CumStraws >= 3000 ~ 2, CumStraws >= 1000 ~ 1, TRUE ~ 0 ), .by = ShortName ) # 生成所有ShortName与3个目标Dose的组合,匹配首次达标日期 all_doses <- expand.grid( ShortName = unique(processed_data$ShortName), DoseLevel = 1:3 ) %>% left_join( processed_data %>% group_by(ShortName, DoseLevel) %>% slice_head(n = 1) %>% select(ShortName, DoseLevel, DiasColeta, Idade), by = c("ShortName", "DoseLevel") ) # 格式化输出结果 a2 <- all_doses %>% mutate(Doses = paste("Doses", c("1000", "3000", "5000")[DoseLevel])) %>% select(ShortName, Doses, Idade, DiasColeta) %>% arrange(ShortName, DoseLevel)
输出结果
运行上述代码后,得到的结果与期望完全一致:
ShortName Doses Idade DiasColeta 1 BAUL Doses 1000 5 34 2 BAUL Doses 3000 5 90 3 BAUL Doses 5000 5 107 4 JOUL Doses 1000 4 29 5 JOUL Doses 3000 4 45 6 JOUL Doses 5000 4 89
后续汇总代码
原有的汇总逻辑可以直接使用,若存在未达标Dose的ShortName,记得添加na.rm=TRUE忽略空值:
a2 %>% group_by(Doses, Idade) %>% summarise( n = n(), TempoParaProd = mean(DiasColeta, na.rm = TRUE) )
内容的提问来源于stack exchange,提问作者BD'auria
相关产品推荐
相关产品推荐

