移除NA后ggplot facet_grid柱状图宽度异常问题求解
问题描述
使用ggplot绘制柱状图时,包含NA的完整数据集生成的图表显示正常,但使用na.omit()移除NA值后,柱状图宽度明显变大。即使提前筛选数据、使用facet_wrap或在facet_grid中添加space='free',问题仍会出现。
示例数据集:
District<-c('Ngorongoro','Ngorongoro','Ngorongoro','Misungwi','Misungwi','Mwanga') Q2<-rep('Retail outlet', 6) Q42<-c('once_per_month','once_per_year','once_per_month',NA,NA,NA) anm<-as.data.frame(cbind(District,Q2,Q42))
完整数据绘图代码:
anm$Q42<-factor(anm$Q42,levels=c('once_per_week','once_per_month', 'once_per_6months','once_per_year')) ggplot(data = anm, aes(x=Q42,fill=District)) + geom_bar() + scale_x_discrete(drop=F)+ scale_fill_discrete(drop=F)+ labs(title="Animal health providers", subtitle='n=3',x="", y="Count") + facet_grid(~Q2)+ ylim(0,6)+ theme(axis.text.x = element_text(angle = 90, hjust=1), plot.title = element_text(face='bold'), text=element_text(size=10))+ stat_count(geom='text',aes(label = ..count..,group=1),vjust=-2,size=2)+ stat_count(geom='text',aes(label = paste0("(",round(..count..*100/3,1),"%)"),group=1),vjust=-0.5,size=2)
移除NA后绘图代码:
ggplot(data = na.omit(anm), aes(x=Q42,fill=District)) + geom_bar() + scale_x_discrete(drop=F)+ scale_fill_discrete(drop=F)+ labs(title="Animal health providers", subtitle='n=3',x="", y="Count") + facet_grid(~Q2)+ ylim(0,6)+ theme(axis.text.x = element_text(angle = 90, hjust=1), plot.title = element_text(face='bold'), text=element_text(size=10))+ stat_count(geom='text',aes(label = ..count..,group=1),vjust=-2,size=2)+ stat_count(geom='text',aes(label = paste0("(",round(..count..*100/3,1),"%)"),group=1),vjust=-0.5,size=2)
问题原因
核心原因是ggplot的默认布局逻辑:
- 你通过
scale_x_discrete(drop=F)强制保留了Q42的所有4个因子水平,即使部分水平没有数据。 - 当使用
na.omit()删除NA行后,数据中仅剩下2个Q42水平有实际观测值,ggplot会自动调整有数据的柱子宽度,使其填充更多面板可用空间(避免空水平导致面板过于稀疏)。 - 而完整数据中存在的NA行,虽然不会被绘制到x轴上,但会影响ggplot的布局计算,使其维持默认的柱子宽度比例。
解决方法
只需在geom_bar()中手动指定固定的柱子宽度,即可确保两种情况下的柱子宽度一致。具体步骤如下:
修改移除NA后的绘图代码,在geom_bar()中添加width参数(比如设置为0.6,可根据需求调整):
ggplot(data = na.omit(anm), aes(x=Q42,fill=District)) + geom_bar(width = 0.6) + # 手动设置柱子宽度 scale_x_discrete(drop=F)+ scale_fill_discrete(drop=F)+ labs(title="Animal health providers", subtitle='n=3',x="", y="Count") + facet_grid(~Q2)+ ylim(0,6)+ theme(axis.text.x = element_text(angle = 90, hjust=1), plot.title = element_text(face='bold'), text=element_text(size=10))+ stat_count(geom='text',aes(label = ..count..,group=1),vjust=-2,size=2)+ stat_count(geom='text',aes(label = paste0("(",round(..count..*100/3,1),"%)"),group=1),vjust=-0.5,size=2)
你也可以将完整数据的绘图代码也加上相同的width参数,确保两张图的柱子宽度完全一致。
内容的提问来源于stack exchange,提问作者Kathrin Loosli
相关产品推荐
相关产品推荐

