ggplot2中geom_col对应geom_text百分比标签对齐调整求助
问题解决:分组柱状图百分比标签对齐调整
问题说明
基于年龄组、健康状态(very good、good、bad)绘制分组柱状图,展示性状态为"yes"时的性活动率百分比,但当前百分比标签按年龄组垂直堆叠,无法对应到对应柱子的末端位置。
原代码
library(tidyverse) library(scales) ageC <- c("18-34","35+", "35+", "35+","35+","18-34","18-34","35+","18-34","35+") health <- c("very good","very good", "bad", "bad", "good", "good", "bad", "very good", "good", "bad") sexuality <- c("yes", "yes", "no", "yes", "yes", "no", "yes", "no", "yes", "no") df <- data.frame(ageC,health,sexuality) df2 <- df %>% select(ageC, health, sexuality) dff2 <- df2 %>% group_by(ageC, health, sexuality) %>% summarise(n = n()) %>% mutate(pct = n / sum(n), sexuality = str_squish(sexuality)) %>% ungroup() |> filter(sexuality == "yes") %>% mutate(health = fct_relevel(health, "very good", "good", "bad")) ggplot(data = dff2) + geom_col(aes(fill = health, y = pct, x = ageC), width = 0.75, position = position_dodge(preserve = "single") ) + scale_y_continuous(label = percent) + scale_fill_manual(values = c("very good" = "#cbd5e8", "good" = "#fdcdac", "bad" = "#b3e2cd" )) + facet_wrap(~sexuality) + labs( x = "Age class", y = "Percentage" ) + expand_limits(y = 1) + theme(text = element_text(family = "Times New Roman", size = 18)) + geom_text(aes(y = pct, x = ageC, group = pct, label = percent(pct, accuracy = .1), family = "Times New Roman"), vjust = 1.2, size = 2)
调整方案
问题核心是geom_text的分组逻辑和位置设置错误,修改后即可让标签与柱子一一对应:
修改后的完整代码
library(tidyverse) library(scales) ageC <- c("18-34","35+", "35+", "35+","35+","18-34","18-34","35+","18-34","35+") health <- c("very good","very good", "bad", "bad", "good", "good", "bad", "very good", "good", "bad") sexuality <- c("yes", "yes", "no", "yes", "yes", "no", "yes", "no", "yes", "no") df <- data.frame(ageC,health,sexuality) df2 <- df %>% select(ageC, health, sexuality) dff2 <- df2 %>% group_by(ageC, health, sexuality) %>% summarise(n = n()) %>% mutate(pct = n / sum(n), sexuality = str_squish(sexuality)) %>% ungroup() |> filter(sexuality == "yes") %>% mutate(health = fct_relevel(health, "very good", "good", "bad")) ggplot(data = dff2) + geom_col(aes(fill = health, y = pct, x = ageC), width = 0.75, position = position_dodge(preserve = "single") ) + scale_y_continuous(label = percent) + scale_fill_manual(values = c("very good" = "#cbd5e8", "good" = "#fdcdac", "bad" = "#b3e2cd" )) + facet_wrap(~sexuality) + labs( x = "年龄组", y = "百分比" ) + expand_limits(y = 1) + theme(text = element_text(family = "Times New Roman", size = 18)) + geom_text(aes(y = pct, x = ageC, group = health, label = percent(pct, accuracy = .1), family = "Times New Roman"), vjust = 1.2, size = 2, position = position_dodge(preserve = "single"))
关键修改点
- 将
geom_text中的group = pct改为group = health:让标签按健康状态分组,匹配柱子的分组逻辑 - 给
geom_text添加position = position_dodge(preserve = "single"):与柱子的位置偏移设置保持一致,确保标签和对应柱子对齐 - 可选优化:将坐标轴标签改为中文,适配中文使用场景
内容的提问来源于stack exchange,提问作者lpambout
相关产品推荐
相关产品推荐

