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

R语言ggplot堆叠条形图标签居中及双Y轴添加问题

问题与解决方案

一、堆叠柱状图数据标签不居中的问题

问题原因

你的geom_bar使用了position_stack(reverse = TRUE)反转了堆叠顺序,但geom_text的position_stack未同步设置reverse = TRUE,导致标签的堆叠方向与柱子的堆叠方向不一致,最终标签无法居中对应区块。

解决方法

方法1:同步堆叠反转设置

修改geom_text的position参数,添加reverse = TRUE,让标签堆叠方向与柱子保持一致:

ggplot(test, aes(x=name, y=value, fill=type)) + 
  geom_bar(position = position_stack(reverse = TRUE), stat='identity') + 
  theme(plot.title = element_text(hjust = 0.5)) +
  scale_fill_manual(values = c("#0099f9", "#69c6ff")) + 
  # 同步设置reverse=TRUE
  geom_text(aes(label = value), position = position_stack(reverse = TRUE, vjust = 0.5), colour = "black", size = 3) + 
  guides(fill = guide_legend(title = "", reverse = TRUE))

方法2:手动计算标签位置(更可控)

预处理数据,计算每个堆叠区块的中点位置,直接指定标签的y坐标:

library(dplyr)
# 按堆叠顺序计算每个区块的中点
test_processed <- test %>%
  arrange(name, desc(type)) %>% 
  group_by(name) %>%
  mutate(cum_value = cumsum(value),
         mid_value = cum_value - value/2)

# 绘图
ggplot(test_processed, aes(x=name, y=value, fill=type)) + 
  geom_bar(position = position_stack(reverse = TRUE), stat='identity') + 
  theme(plot.title = element_text(hjust = 0.5)) +
  scale_fill_manual(values = c("#0099f9", "#69c6ff")) + 
  geom_text(aes(y=mid_value, label=value), colour="black", size=3) + 
  guides(fill = guide_legend(title = "", reverse = TRUE))

二、添加百分比双Y轴的实现

通过sec_axis实现双轴,需先建立百分比与原数值轴的映射关系:

步骤1:预处理数据

# 将百分比转为数值格式
test2 <- test2 %>%
  mutate(share_num = as.numeric(sub("%", "", share))/100)

# 计算原数据的最大值,用于建立轴的映射关系
max_total <- test %>%
  group_by(name) %>%
  summarise(total = sum(value)) %>%
  pull(total) %>%
  max()

步骤2:绘制双轴图表

ggplot() +
  # 原堆叠柱状图
  geom_bar(data=test, aes(x=name, y=value, fill=type), 
           position=position_stack(reverse=TRUE), stat='identity') +
  # 添加百分比标签(位置可根据需求调整)
  geom_text(data=test2, aes(x=name, y=max_total*share_num, label=share), 
            colour="darkred", size=3, hjust=-0.1) +
  # 设置主、次Y轴
  scale_y_continuous(
    name = "数值",
    sec.axis = sec_axis(
      ~./max_total, 
      name = "占比 (%)",
      labels = function(x) paste0(round(x*100), "%")
    )
  ) +
  scale_fill_manual(values = c("#0099f9", "#69c6ff")) +
  theme(
    plot.title = element_text(hjust=0.5),
    axis.title.y.right = element_text(colour="darkred"),
    axis.text.y.right = element_text(colour="darkred")
  ) +
  guides(fill = guide_legend(title = "", reverse = TRUE))

说明

  • 次轴是视觉映射的虚拟轴,需确保百分比与原数值的转换关系正确;
  • 可通过调整geom_text的hjust、y参数修改百分比标签的显示位置。

内容的提问来源于stack exchange,提问作者Who

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 14:05:53