如何用{ggrepel}调整环形图标签位置,避免与图重叠
解决环形图标签与图形重叠问题
问题背景
使用R的ggplot2和ggrepel制作环形图时,标签容易与环形区域重叠,希望将四个标签分别固定在图的左上、右上、左下、右下外侧位置,与环形保持足够间距。
解决方案
核心思路是手动计算标签的锚点位置,避免ggrepel自动布局的不确定性,同时调整绘图范围和标签参数确保布局符合预期。
修改后的完整代码
library(tidyverse) library(ggrepel) # 创建示例数据框 data <- data.frame(Column = c("v1", "v2", "v3", "v4"), Value = c(86.5, 12.9, 0.0, 0.6), Color = c("#007bc9", "#a50021", "#5ad5ff", "#002f80"), Category = c("A", "B", "C", "D"), Title = c("Variable 1", "Variable 2", "Variable 3", "Variable 4")) # 自定义环形内孔大小 hsize <- 2 # 计算每个类别的角度中间位置(用于标签锚点) data <- data %>% arrange(desc(Value)) %>% mutate( end = cumsum(Value), start = lag(end, default = 0), mid = (start + end)/2 ) # 创建环形图 donut <- data %>% ggplot(aes(x = hsize, y = Value, fill = Category)) + geom_col() + coord_polar(theta = "y") + scale_fill_manual(values = data$Color) + # 扩大x轴范围,给外侧标签留出足够空间 xlim(c(0.1, hsize + 1.8)) + labs(x = "", y = "") + ggtitle("Title") + theme( plot.background = element_rect(fill = "white", color = NA), panel.background = element_rect(fill = "white", color = NA), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), plot.title = element_text( color = "#002f80", face = "bold", hjust = 0.5, size = 16 ), axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.text.y = element_blank(), axis.ticks.y = element_blank() ) + guides(fill = "none") + scale_y_reverse() # 添加外侧标签,手动指定锚点位置 donut <- donut + geom_label_repel( aes(x = hsize + 1.2, y = mid, label = paste0(Title, "\n", if_else(Value == 0, "0%", paste0(Value, "%")))), color = "#002f80", size = 4, fill = "white", box.padding = 0.8, force = 2, force_pull = 0, # 关闭向内拉力,防止标签靠近环形 nudge_x = 0.2, # 稍微向外推标签,增加间距 segment.size = 0.7, direction = "y" # 限制标签仅在垂直半径方向调整,保证布局符合预期 ) print(donut)
关键修改说明
手动计算锚点位置
通过累计Value得到每个类别的角度范围,取中间值mid作为标签在极坐标y轴(角度轴)的锚点;同时将标签的x坐标设为hsize+1.2,确保锚点位于环形图外侧。扩大绘图范围
将xlim的上限从hsize+0.5调整为hsize+1.8,给外侧标签留出足够的显示空间,避免被截断。优化ggrepel参数
force_pull=0:关闭标签向内的拉力,彻底避免标签被拉回环形区域nudge_x=0.2:将标签稍微向外推,进一步增加与环形的间距direction="y":限制标签仅在垂直于半径的方向调整,确保四个标签分别落在左上、右上、左下、右下的预期位置
兼容0值类别
即使类别Value为0,通过累计计算的mid值仍能准确定位,标签会出现在对应角度的外侧,不会出现重叠或丢失。
内容的提问来源于stack exchange,提问作者Brian Lookabaugh
相关产品推荐
相关产品推荐

