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

在R中使用Plotly设置多饼图边距遇问题:图表重叠

解决多饼图标签重叠问题:Plotly 修复方案与 ggplot2 替代实现

Plotly 修复子饼图重叠及标签溢出

你的问题在于margin参数仅控制整个图表的外边缘,子图之间的间距需要通过layout的grid参数调整,同时每个饼图的domain范围需要缩小,避免标签溢出到相邻子图。

修改后的完整代码

library(plotly)
library(dplyr)

labels <- rep(LETTERS[seq(from = 1, to = 11)],12)
values <- runif(length(labels), min=0, max=1)
group <- letters[seq(from = 1, to = 12)]
# 将行/列转换为0-1的比例值,便于精准控制饼图范围
row <- rep(seq(0, 3)/4, each=3)
col <- rep(seq(0, 2)/3, time=4)
d1 <- data.frame(labels, values, group)

pie_colors <- rainbow(11) # 定义饼图颜色

p <- plot_ly() 
for (i in 1:12) {
  var <- group[i] 
  d <- d1 %>% filter(group == var) 
  # 缩小饼图的domain范围,为外部标签预留空间
  row_range <- c(row[i] + 0.03, row[i] + 1/4 - 0.03)
  col_range <- c(col[i] + 0.03, col[i] + 1/3 - 0.03)
  
  p <- p %>% add_pie(
    data = d, 
    labels = ~labels, 
    values = ~values, 
    type = 'pie',
    textposition = "outside", 
    textinfo = 'label+percent',
    marker = list(colors = pie_colors),
    sort = FALSE,
    domain = list(row = row_range, column = col_range),
    textfont = list(size = 10) # 缩小标签字体,避免溢出
  )
}

p <- p %>% layout(
  title = NULL, 
  showlegend = FALSE,
  # 设置子图之间的行/列间距
  grid = list(rows = 4, columns = 3, rowgap = 0.12, colgap = 0.12),
  margin = list(b = 40, l = 40, r = 40, t = 40),
  xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
  yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE)
)

p

# 导出时适当调整尺寸,保证标签完整
orca(p, "pie_chart.pdf", scale = 1.2, width = 1400, height = 1800)

核心修改点

  • 将row/col转换为0-1的比例值,替代原整数索引,便于精准控制饼图的显示范围
  • 为每个饼图的domain设置缩小的范围,避免标签溢出到相邻子图
  • 在grid中添加rowgap和colgap参数,直接控制子图之间的间距
  • 调整textfont大小,进一步减少标签溢出风险

ggplot2 实现类似Plotly的外部标签效果

如果偏好ggplot2生态,可使用ggforce绘制饼图,配合ggrepel实现无重叠的外部标签:

完整代码

library(ggplot2)
library(ggforce)
library(ggrepel)
library(dplyr)

labels <- rep(LETTERS[seq(from = 1, to = 11)],12)
values <- runif(length(labels), min=0, max=1)
group <- letters[seq(from = 1, to = 12)]
d1 <- data.frame(labels, values, group)

# 计算每个饼块的角度、中点及外部标签位置
d1 <- d1 %>%
  group_by(group) %>%
  mutate(
    value_norm = values / sum(values),
    end = 2 * pi * cumsum(value_norm),
    start = lag(end, default = 0),
    mid = (start + end) / 2,
    # 计算向外偏移的标签坐标
    label_x = 1.2 * cos(mid),
    label_y = 1.2 * sin(mid),
    percent = sprintf("%.1f%%", value_norm * 100),
    label_text = paste(labels, percent, sep = "\n")
  ) %>%
  ungroup()

# 绘制多子图饼图
ggplot(d1, aes(x0 = 0, y0 = 0, r0 = 0, r = 1, start = start, end = end, fill = labels)) +
  geom_arc_bar(alpha = 0.8) +
  geom_text_repel(
    aes(x = label_x, y = label_y, label = label_text),
    size = 3,
    nudge_x = 0.1 * sign(cos(mid)),
    nudge_y = 0.1 * sign(sin(mid)),
    segment.color = "gray50"
  ) +
  coord_fixed() +
  facet_wrap(~group, nrow = 4, ncol = 3) +
  theme_void() +
  theme(
    strip.text = element_blank(),
    legend.position = "none",
    panel.spacing = unit(1, "cm") # 调整子图间距
  ) +
  scale_fill_manual(values = rainbow(11))

说明

  • 手动计算饼块的角度参数,为外部标签定位
  • geom_text_repel自动处理标签重叠问题,并添加连接线模拟Plotly效果
  • panel.spacing控制子图之间的间距,避免布局拥挤

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:34:56