为水平ggplot条形图设置双Y轴标签(identity统计)
解决ggplot双Y轴标签布局异常问题
问题背景
现有df_long数据集,需绘制水平堆叠条形图展示多项选择结果,希望将Y轴标签拆分到左右两侧分别显示,但尝试添加双Y轴的代码导致图表显示异常,需修复以实现预期布局。
问题分析
原代码存在以下问题:
- Y轴刻度范围设置错误:
limits = c(0, length(vlabs1))将下限设为0,但as.numeric(comp_name)的取值是1到13(对应13个因子水平),导致条形位置偏移、标签对齐混乱 - 右侧Y轴标签样式未单独设置,默认继承左侧样式,显示效果不佳
- 未确认
vlabs1和vlabs2的顺序是否与comp_name的因子水平完全匹配,导致标签对应关系错误
修正方案
以下是修复后的完整代码,关键修改点已标注:
# 定义左右侧Y轴标签,确保顺序与comp_name的因子水平完全对应 vlabs1 <- c( "Less Smart Person", "Less Smart Person", "Less Smart Person", "Less Smart Person", "Really Smart Monkey", "Really Smart Monkey", "Really Smart Person", "Really Smart Person", "Really Smart Person", "Really Smart Person", "Really Smart Person", "Really Smart Person", "Really Smart Person" ) vlabs2 <- c( "5 Less Smart Monkeys", "5 Really Smart Monkeys", "Less Smart Monkey", "Really Smart Monkey", "5 Less Smart Monkeys", "Less Smart Monkey", "5 Less Smart Monkeys", "5 Less Smart People", "5 Really Smart Monkeys", "Less Smart Monkey", "Less Smart Person", "Really Smart Monkey", "Super Smart Monkey" ) ggplot(df_long, aes(y = as.numeric(comp_name), x = DV, fill = as.factor(DV))) + geom_bar(stat = "identity", position = "fill") + scale_fill_manual( name = "", values = c("cornflowerblue", "grey", "sandybrown"), labels = c("Person/Smarter", "Can't Decide", "Monkey/Dumber") ) + labs( title = "Are Children More Speciesist Than Adults?", y = NULL, x = NULL, legend = NULL ) + scale_x_continuous( breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), labels = c("0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%") ) + # 修正Y轴范围和刻度,与as.numeric(comp_name)的取值(1-13)匹配 scale_y_continuous( limits = c(1, length(vlabs1)), breaks = 1:length(vlabs1), labels = vlabs1, sec.axis = sec_axis( ~., breaks = 1:length(vlabs2), labels = vlabs2 ) ) + theme_minimal() + theme( text = element_text(size = 15), # 设置左侧Y轴标签样式 axis.text.y.left = element_text(size = 13, color = "grey40"), # 设置右侧Y轴标签样式,确保显示正常 axis.text.y.right = element_text(size = 13, color = "grey40"), axis.text.x = element_text(color = "black", size = 14), axis.line.x = element_line(color = "black"), legend.position = "bottom", legend.spacing.y = unit(0.2, "cm"), plot.title = element_text(hjust = 0.5, size = 16), # 增大右侧边距,避免标签被截断 plot.margin = unit(c(5,15,5,5),"mm") ) + guides(fill = guide_legend(reverse = TRUE))
关键修改说明
- 标签顺序修正:重新调整
vlabs1和vlabs2的顺序,确保每个元素与comp_name的因子水平一一对应(可通过levels(df_long$comp_name)查看原始顺序) - Y轴范围修正:将
limits改为c(1, length(vlabs1)),匹配as.numeric(comp_name)的实际取值范围,确保条形和标签对齐 - 右侧标签样式设置:新增
axis.text.y.right配置,单独控制右侧标签的样式,避免继承左侧的错误设置 - 边距调整:增大右侧边距,防止长标签被图表边缘截断
内容的提问来源于stack exchange,提问作者Carter Allen
相关产品推荐
相关产品推荐

