ggplot coord_polar饼图中geom_text标签定位与重叠问题求解
饼图标签错位与重叠问题解决方案
问题分析
你的代码存在两个核心问题:
- ggplot默认对离散类别按字母排序,导致扇形顺序与标签顺序不匹配,出现错位;
- 小占比类别的标签未做偏移处理,直接堆叠导致重叠。
解决方案代码
基础版(使用position_jitter)
library(dplyr) library(ggplot2) patents <- read.csv2("sample.csv") # 统计频次、计算百分比并固定类别顺序 patents <- patents %>% count(country, sort = FALSE) %>% # sort=FALSE保留原始类别顺序,如需按占比排序设为TRUE mutate( pct = round(n / sum(n) * 100, 1), country = factor(country, levels = country) # 锁定类别顺序,避免ggplot自动重排 ) ggplot(patents, aes(x = "", y = pct, fill = country)) + geom_bar(stat = "identity", colour = "black", size = 0.05) + geom_text( aes(label = paste0(pct, "%")), x = 1.3, # 先将标签对齐扇形中心,再添加随机偏移解决重叠 position = position_stack(vjust = 0.5) %>% position_jitter(width = 0.05, height = 0.2), size = 3 ) + coord_polar("y") + theme_void() + scale_fill_discrete(limits = levels(patents$country)) # 确保填充色顺序与类别一致
优化版(使用ggrepel更稳定)
如果小占比类别较多,推荐用ggrepel包自动避免标签重叠:
library(dplyr) library(ggplot2) library(ggrepel) patents <- read.csv2("sample.csv") patents <- patents %>% count(country, sort = FALSE) %>% mutate( pct = round(n / sum(n) * 100, 1), country = factor(country, levels = country) ) ggplot(patents, aes(x = "", y = pct, fill = country)) + geom_bar(stat = "identity", colour = "black", size = 0.05) + geom_text_repel( aes(label = paste0(pct, "%")), position = position_stack(vjust = 0.5), x = 1.3, size = 3, min.segment.length = 0 # 强制显示标签与扇形的连接线 ) + coord_polar("y") + theme_void() + scale_fill_discrete(limits = levels(patents$country))
关键步骤说明
- 固定类别顺序:通过
factor(country, levels = country)将country转为因子,保留统计后的类别顺序,彻底解决ggplot自动排序导致的标签错位问题。 - 对齐标签到扇形中心:
position_stack(vjust = 0.5)让标签自动定位到对应扇形的垂直中点,替代手动设置x位置的粗糙方式。 - 解决标签重叠:
- 基础版用
position_jitter在堆叠位置基础上添加随机偏移,参数width和height可根据实际情况调整; - 优化版用
geom_text_repel自动计算无重叠的标签位置,连接线能清晰对应标签与扇形,可读性更强。
- 基础版用
内容的提问来源于stack exchange,提问作者Vitor Hugo Moreau
相关产品推荐
相关产品推荐

