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

求助:制作带外部连线标签的Donut Chart(环形图)

环形图(Donut Chart)外部连线标签实现方案

问题说明

我想要制作一个带有标签的环形图(Donut Chart),标签需置于图表外部并通过连线对应到环形的相应部分。以下是我目前完成的代码,但无法实现连线效果,且存在标签重叠问题。

原始代码

数据框

geschlecht <- as.data.frame(tibble(
  gender = as.factor(c("männlich", "weiblich", "nicht-binär", "keine Angabe")),
  count = c(46, 43, 7, 4)
))

计算百分比

geschlecht <- geschlecht %>% mutate(fraction = count / sum(count),
                    ymax = cumsum(fraction),
                    ymin = c(0, head(ymax, n=-1)),
                    labelPosition = (ymax + ymin)/2,
                    label = paste0(gender,"\n",count, "%"))

创建环形图

geschlecht_donut <- ggplot(geschlecht, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=gender)) +
  geom_rect() +
  geom_label( x=3.5, aes(y=labelPosition, label=label), size=6) +
  coord_polar(theta="y") +
  xlim(c(2, 4)) +
  
  scale_fill_brewer(palette = "OrRd") +
  theme(legend.position = "none") +
  theme_void() +
  guides(
    fill = "none")

geschlecht_donut

解决方案

要实现外部标签+连线的效果,需要调整标签位置计算逻辑,并添加连线图层,具体修改如下:

修改后的完整代码

library(ggplot2)
library(dplyr)
library(tibble)

# 数据框
geschlecht <- as.data.frame(tibble(
  gender = as.factor(c("männlich", "weiblich", "nicht-binär", "keine Angabe")),
  count = c(46, 43, 7, 4)
))

# 计算百分比及标签位置参数
geschlecht <- geschlecht %>% 
  mutate(fraction = count / sum(count),
         ymax = cumsum(fraction),
         ymin = c(0, head(ymax, n=-1)),
         labelPosition = (ymax + ymin)/2,
         # 转换为角度,用于判断标签左右位置
         angle = labelPosition * 360,
         # 根据角度设置标签对齐方式
         hjust = ifelse(angle > 180, 1, 0),
         # 设置标签的x轴位置(外部)
         label_x = ifelse(angle > 180, 4.5, 4.5),
         # 标签文本换行
         label = paste0(gender,"\n",count, "%"))

# 创建带外部连线标签的环形图
geschlecht_donut <- ggplot(geschlecht, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=gender)) +
  # 环形主体
  geom_rect() +
  # 绘制从环形到标签的连线
  geom_segment(aes(x = 4, xend = label_x, 
                   y = labelPosition, yend = labelPosition,
                   color = gender),
               size = 1) +
  # 外部标签
  geom_text(aes(x = label_x, y = labelPosition, 
                label = label, hjust = hjust),
            size = 6) +
  coord_polar(theta="y") +
  # 扩展x轴范围,给外部标签留出空间
  xlim(c(2, 5)) +
  scale_fill_brewer(palette = "OrRd") +
  scale_color_brewer(palette = "OrRd") +
  theme_void() +
  theme(legend.position = "none")

geschlecht_donut

关键修改点

  • 角度判断:将标签位置转换为角度,以此区分标签在图表左侧还是右侧,调整对齐方式避免文本反向显示。
  • 连线图层:用geom_segment绘制环形边缘到外部标签的连线,保证标签与对应区块精准关联。
  • 标签位置优化:根据角度设置标签的x坐标,同时扩展x轴范围,避免标签重叠。
  • 样式调整:用geom_text替代geom_label减少视觉干扰,也可保留geom_label并调整样式适配需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:14:57