如何在ggplot的发散条形图中将数值标签居中于条形内部?
问题
我用ggplot绘制了多幅发散条形图,当前代码把数值标签放在条形的上下方,想改成将标签置于条形的水平和垂直中心位置。试过position = position_stack(vjust = .5)但没成功。
原代码和数据集如下:
原代码
library(ggplot2) # 注:原代码写的ggplot是笔误,应为ggplot2 library(gridExtra) # 导入百分比变化数据集 LC_Pct_Change <- read.csv("LC_%_Change_SA.csv", header=T) # 创建单时段图表 PC_1930_1960 <- ggplot(LC_Pct_Change, aes(x=Land_Cover_Category, y=Change_1930_1960)) + geom_bar(stat="identity", fill=ifelse(LC_Pct_Change$Change_1930_1960<0,"darksalmon", "darkseagreen2"), show.legend = FALSE) + geom_text(aes(label = round(Change_1930_1960, 1), hjust = 0.5, vjust = ifelse(Change_1930_1960 < 0, 1.5, -1)), size = 2.5) + ggtitle("1930-1960") + xlab("土地覆盖类型") + ylab("% 变化率") + theme_bw() + scale_x_discrete(limits = c("W", "R", "G", "A", "U")) # 为其余时段重复上述代码 # 合并所有图表并导出 PC_All <- grid.arrange(PC_1930_1960, PC_1960_1990, PC_1990_2000, PC_2000_2007, PC_2007_2015, PC_2015_2020, PC_1930_2020, ncol=3)
补充数据集
LC_Pct_Change <- structure(list( Land_Cover_Category = c("W", "R", "G", "A", "U"), Change_1930_1960 = c(1.984932164, -3.628139858, -1.446064637, 2.20879849, 0.880473841), Change_1960_1990 = c(1.56838857, -7.920867205, -1.967420952, 6.078769876, 2.241129711), Change_1990_2000 = c( 1.54170708, 0.909136716, -7.092356282, -2.215064057, 6.856576543 ), Change_2000_2007 = c(-1.244727434, 5.104227969, -0.328826854, 3.025170368, -6.555844049), Change_2007_2015 = c(1.254510492, -6.750375486, 5.846903583, -2.837464028, 2.486425439), Change_1990_2020 = c(2.549684204, -0.821752298, -1.872783653, -3.277412153, 3.4222639), Change_1930_2020 = c(6.103004939, -12.37075936, -5.286269243, 5.010156213, 6.543867451) ), class = "data.frame", row.names = c(NA, -5L))
解决方案
要让标签居中,核心是让标签的y坐标对应条形的中点,同时设置水平和垂直对齐为居中。修改geom_text的参数即可实现,同时可以优化颜色映射的写法:
修改后的单时段代码示例
PC_1930_1960 <- ggplot(LC_Pct_Change, aes(x=Land_Cover_Category, y=Change_1930_1960)) + # 优化颜色映射:将fill放入aes,用scale_fill_manual定义颜色,更符合ggplot逻辑 geom_bar(stat="identity", aes(fill = Change_1930_1960 < 0), show.legend = FALSE) + scale_fill_manual(values = c("FALSE" = "darkseagreen2", "TRUE" = "darksalmon")) + # 调整geom_text:y设为变化值的一半(条形中点),同时设置居中对齐 geom_text(aes(y = Change_1930_1960/2, label = round(Change_1930_1960, 1)), hjust = 0.5, vjust = 0.5, size = 2.5) + ggtitle("1930-1960") + xlab("土地覆盖类型") + ylab("% 变化率") + theme_bw() + scale_x_discrete(limits = c("W", "R", "G", "A", "U"))
关键说明
- 发散条形的中点坐标:正值条形从0延伸到
Change_xxx,中点是Change_xxx/2;负值条形从0延伸到Change_xxx(负数),中点同样是Change_xxx/2,这个坐标刚好落在条形中心。 - 把颜色判断放入
aes后,用scale_fill_manual指定颜色,比直接在fill里写ifelse更清晰,也方便后续调整颜色。 - 无需再用条件判断
vjust,直接设置vjust=0.5配合中点y值,就能实现垂直居中;hjust=0.5保证水平居中。
只需将其余时段的图表代码做同样修改,再合并导出即可得到标签居中的发散条形图。
内容的提问来源于stack exchange,提问作者Xandian97
相关产品推荐
相关产品推荐

