如何基于分面聚合结果在ggplot中筛选子集?
解决ggplot分面仅保留占比达标分组的问题
我完全懂你的需求——你有包含多分组的数据集,想在ggplot分面时只保留那些占某一指标总和比例达标的分组,但之前的尝试没成功,核心问题是你的subset写法没有按分组计算占比,导致所有分组都被保留了。
问题出在哪?
你之前的subset代码里:
subset(iris, round(100*sum(Petal.Length)/sum(iris$Petal.Length)) >= 30)
这里的sum(Petal.Length)是对整个iris数据集的花瓣长度求和,不是按Species分组计算的。所以这个条件对每一行数据来说都是同一个固定值,自然所有行都被保留,分面也就显示了全部3个物种。
正确的解决方法
我们需要先按分组计算占比,筛选出符合条件的分组,再用这些分组去过滤原始数据,最后绘图。
步骤1:筛选符合条件的分组
先计算每个分组的占比,提取出符合要求的分组名称:
library(tidyverse) # 计算每个物种的花瓣长度占比,筛选占比≥30%的物种 selected_groups <- iris %>% group_by(Species) %>% summarise(group_total = sum(Petal.Length)) %>% mutate(percentage = 100 * group_total / sum(group_total)) %>% filter(percentage >= 30) %>% pull(Species) # 把筛选后的物种名称转为向量
步骤2:过滤数据并绘图
用筛选出的分组向量过滤原始数据,再进行ggplot绘图:
iris.sub <- ggplot(iris %>% filter(Species %in% selected_groups), aes(x = ' ', y = Petal.Length)) + geom_point(stat = 'summary', fun = 'mean') + geom_errorbar(stat = 'summary', fun.data = 'mean_se', width = 0, fun.args = list(mult = 1.96)) + facet_grid(. ~ Species) + theme_bw() iris.sub
也可以用管道一步完成
如果你喜欢更简洁的写法,把数据处理和绘图用管道连起来:
iris %>% group_by(Species) %>% mutate(group_total = sum(Petal.Length)) %>% mutate(percentage = 100 * group_total / sum(.$Petal.Length)) %>% filter(percentage >= 30) %>% ungroup() # 取消分组,避免后续ggplot的自动分组问题 ggplot(aes(x = ' ', y = Petal.Length)) + geom_point(stat = 'summary', fun = 'mean') + geom_errorbar(stat = 'summary', fun.data = 'mean_se', width = 0, fun.args = list(mult = 1.96)) + facet_grid(. ~ Species) + theme_bw()
这样处理后,你的ggplot分面就只会显示占比≥30%的分组了,对应iris数据集里的2个物种。
内容的提问来源于stack exchange,提问作者Khashir
相关产品推荐
相关产品推荐

