含负值时如何让geom_text位于geom_bar正上方?
解决ggplot2中geom_text仅显示在正数值条形上方的问题
问题描述
现有基于tidyverse的ggplot2代码生成的图表中,geom_text默认定位在整体数据集的组比例对应y轴位置,需求是让文本仅出现在正数值对应的条形上方,同时保留「百分比 | 计数」的标签格式。
原始数据集与代码
数据集
# A tibble: 15 x 3 group variable value <int> <fct> <int> 1 1 1 0 2 1 2 0 3 1 3 -2 4 2 1 1 5 2 2 -2 6 2 3 1 7 3 1 -1 8 3 2 -2 9 3 3 -2 10 4 1 0 11 4 2 -1 12 4 3 2 13 5 1 0 14 5 2 1 15 5 3 -2
原始代码
library(tidyverse) df %>% ggplot() + aes(x = group ,weight = value) + geom_bar(aes(y = after_stat(proportions(count)), fill = variable), stat = "count") + coord_flip() + geom_hline(yintercept = 0) + geom_text(aes(y = after_stat(proportions(count)), label = str_c(percent(after_stat(proportions(count))), " | ", after_stat(count))), stat = "count")
修改后的解决方案代码
library(tidyverse) # 加载测试数据 df <- structure(list(group = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L), variable = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), levels = c("1", "2", "3"), class = "factor"), value = c(0L, 0L, -2L, 1L, -2L, 1L, -1L, -2L, -2L, 0L, -1L, 2L, 0L, 1L, -2L)), row.names = c(NA, -15L), class = c("tbl_df", "tbl", "data.frame")) df %>% ggplot() + aes(x = group, weight = value) + # 保留原条形图绘制逻辑 geom_bar(aes(y = after_stat(proportions(count)), fill = variable), stat = "count") + coord_flip() + geom_hline(yintercept = 0) + # 调整geom_text:仅在正数值条形上方显示文本 geom_text( aes( y = after_stat(proportions(count)) + 0.02, # 添加小偏移让文本位于条形顶端上方 label = str_c(percent(after_stat(proportions(count))), " | ", after_stat(count)) ), stat = "count", # 过滤仅处理value>0的条目 data = . %>% filter(value > 0) )
关键修改说明
- 筛选正数值条目:通过
data = . %>% filter(value > 0)限定geom_text只处理value为正的行,避免在负数值或零值位置生成文本; - 调整文本位置:在y轴映射中添加
+ 0.02的偏移量,让文本与条形顶端保持距离,避免重叠; - 保留原有标签逻辑:维持「百分比 | 计数」的标签格式,保证信息展示的一致性。
内容的提问来源于stack exchange,提问作者HoelR
相关产品推荐
相关产品推荐

