R语言按分组计算百分位 合并低于阈值行至Others汇总行
原代码问题
- 分位数计算未按分组执行:直接调用
quantile(df$Flowers, 0.7)取的是全数据集的全局阈值,不是每个Year组内的70分位值,跨组计算逻辑错误 - 判断条件量纲不匹配:用行排名序号
a和Flowers的分位数值做大小比较,两个指标含义完全不同,判断逻辑从根本上不成立 - 冗余步骤过多:不需要额外创建
a列做中间标记,也不需要多次重复分组
可直接运行的实现代码
library(dplyr) df_Others <- df %>% # 按年份分组,所有计算在组内独立完成 group_by(Year) %>% # 计算组内70分位阈值,标记低于阈值的条目归为Others mutate( group_threshold = quantile(Flowers, 0.7), SciName = if_else(Flowers < group_threshold, "Others", as.character(SciName)) ) %>% # 按年份+处理后的物种名分组,汇总花数总和 group_by(Year, SciName) %>% summarise(Flowers = sum(Flowers), .groups = "drop") %>% # 排序:同一年份下原物种按花数降序排,Others固定在组内最后 arrange(Year, SciName == "Others", desc(Flowers))
效果说明
- 所有分位数计算严格在单个年份组内执行,不会出现跨组阈值混用的问题
- 直接用每行Flowers数值和组内阈值做判断,逻辑匹配需求
- 用提供的测试样例运行,输出完全匹配预期结果:
- 2004年组70分位阈值为1700,高于阈值的Liliac(2000)、Rose(3000)保留原名,Daisy(10)、Lily(5)求和为15归为Others
- 2005年组70分位阈值为2200,高于阈值的Lily(5000)、Daisy(1000)保留原名,Liliac(20)、Rose(3)求和为23归为Others
注意:如果需求是保留每组内花数排名前30%的条目(而非数值大于70分位点),把标记逻辑替换为按行排名判断即可,代码如下:
mutate( row_rank = row_number(desc(Flowers)), total_rows = n(), SciName = if_else(row_rank > total_rows * 0.7, "Others", as.character(SciName)) )两种逻辑的区别是:前者按数值大小卡阈值,后者按排名占比卡保留数量,按需选择即可。如果需要把刚好等于分位值的条目保留为原分类,调整判断条件的大于/小于等于符号即可。
内容的提问来源于stack exchange,提问作者Curious_Fish
相关产品推荐
相关产品推荐

