添加手动图例致X轴扩展的ggplot技术问题排查
问题原因解析
- X轴意外扩展的核心原因是
geom_rect中设置的xmin=0和xmax=11超出了离散X轴的实际范围:
ggplot会自动将离散型X轴(Site是分类变量)映射为连续数值,你数据里的8个分类对应1到8的区间。设置xmax=11会强制拉宽X轴范围到11,导致右侧出现大量空白扩展。 - 额外冗余操作:开头的
group_by(Site)完全没必要,ggplot绘制箱线图时会自动按X轴分类分组;全局aes里的fill=cut(Phosphate,...)没有实际作用(你给geom_boxplot手动指定了填充色),还会造成不必要的映射冲突。
修复方案及修改后代码
- 调整
geom_rect的xmin和xmax为离散X轴的实际边界:设xmin=0.5(第一个分类的左侧)、xmax=8.5(最后一个分类的右侧),让背景矩形刚好覆盖所有分类的X轴区域。 - 移除冗余的
group_by(Site)。 - 移除全局
aes中无用的fill映射。
修改后的代码:
df %>% ggplot(aes(x = Site, y = Phosphate)) + # 调整xmin/xmax匹配8个分类的X轴范围 geom_rect(aes(ymin = 0, ymax = 0.069, xmin = 0.5, xmax = 8.5, fill = '0-0.069'), alpha=.1) + geom_rect(aes(ymin = 0.069, ymax = 0.173, xmin = 0.5, xmax = 8.5, fill = '0.069-0.173'), alpha=.1) + geom_rect(aes(ymin = 0.173, ymax = 1.003, xmin = 0.5, xmax = 8.5, fill = '0.173-1.003'), alpha=.1) + geom_rect(aes(ymin = 1.003, ymax = 12, xmin = 0.5, xmax = 8.5, fill = '1.003-12'), alpha=.1) + geom_boxplot(fill="darkolivegreen3") + scale_y_continuous(expand = c(0, 0), limits = c(0, 12)) + scale_x_discrete(limits = c("cell_1_t", "cell_1_b", "cell_2_t", "cell_2_b", "cell_3_t", "cell_3_b", "river_mun_us ", "river_mun_ds"), labels = c("Cell 1 Top", "Cell 1 Bottom", "Cell 2 Top", "Cell 2 Bottom", "Cell 3 Top", "Cell 3 Bottom", "River Upstream", "River Downstream"), expand = c(0, 0)) + annotate(geom = "text", x = 1:6, y = 1, fontface = "bold", label = "(15)") + annotate(geom = "text", x = 7, y = 3, fontface = "bold", label = "(15)") + annotate(geom = "text", x = 8, y = 5, fontface = "bold", label = "(15)") + ggtitle("River Mun ICW") + ylab(expression("Phosphate (mg P L"^-1*")")) + xlab(NULL) + scale_fill_manual(name = 'Water Quality', breaks = c('0-0.069', '0.069-0.173', '0.173-1.003', '1.003-12'), labels = c('Good', 'Moderate', 'Poor', 'Bad'), values = c('bisque4', 'bisque3', 'bisque2', 'bisque')) + theme_bw() + theme(plot.title = element_text(hjust = 1, vjust = -10), axis.text.x = element_text(angle = 90, vjust = 1, hjust = 1, size = 12))+ theme(legend.position = c(.9, .75), legend.background = element_rect(fill = "transparent"))
内容的提问来源于stack exchange,提问作者Erin
相关产品推荐
相关产品推荐

