You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 06:45:53