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

如何绘制以饼图为单元格的类热图可视化?

饼图矩阵替代热图的优化实现建议

我想用多个饼图组成的可视化替代常规矩阵热图来优化数据展示,目前已有基础实现,但还需要完善百分比标注、行列间距等功能,以下是现有代码和生成效果,求改进建议或更优实现方法:

现有实现代码

library(ggplot2)
library(gridExtra)  # 用于排列图形
library(dplyr)
library(plyr)

# 模拟数据
set.seed(123)
data <- expand.grid(X = factor(1:20), Y = factor(1:18))
data$Category <- rep(c("A", "B", "C"), each = 120)
data$Value <- runif(360)

# 查看数据
print(data)

# 绘制单个饼图的函数
plot_pie <- function(data_subset) {
  ggplot(data_subset, aes(x = "", y = Value, fill = Category)) +
    geom_bar(width = 1, stat = "identity") +
    coord_polar(theta = "y") +
    theme_void() +
    theme(legend.position = "none")
}

# 按X和Y分组生成饼图列表
plots <- dlply(data, .(X, Y), plot_pie)

# 使用gridExtra排列图形
grid.arrange(grobs = plots, ncol = 20)

# 也可以用patchwork排列
library(patchwork)
plot_layout <- wrap_plots(plots, ncol = 20)
plot_layout

现有生成效果

饼图矩阵可视化效果

改进建议与优化实现方案

1. 添加百分比标注

先在数据预处理阶段计算每个(X,Y)组内各分类的占比,再在饼图上添加文本标注,确保标注位置准确:

# 预处理数据:计算每组内的百分比与标注位置
data_processed <- data %>%
  group_by(X, Y) %>%
  mutate(Percent = Value / sum(Value) * 100,
         # 计算饼图标注的中心角度位置
         Position = cumsum(Value) - 0.5 * Value) %>%
  ungroup()

# 更新饼图绘制函数,添加百分比标注
plot_pie_with_label <- function(data_subset) {
  ggplot(data_subset, aes(x = "", y = Value, fill = Category)) +
    geom_bar(width = 1, stat = "identity") +
    # 添加保留1位小数的百分比标注
    geom_text(aes(y = Position, label = sprintf("%.1f%%", Percent)),
              size = 2) +  # 根据饼图尺寸调整字号
    coord_polar(theta = "y") +
    theme_void() +
    theme(legend.position = "none",
          # 调整小图边距,避免标注溢出
          plot.margin = margin(1, 1, 1, 1, "mm"),
          # 固定饼图宽高比,保证所有饼图形状一致
          aspect.ratio = 1)
}

2. 调整行列间距与统一布局

使用patchwork更灵活地控制行列间距、整体布局,同时提取统一图例避免重复:

library(patchwork)
library(purrr)

# 用dplyr+ purrr替代plyr生成饼图列表,性能更优
plots_list <- data_processed %>%
  group_by(X, Y) %>%
  group_split() %>%
  map(plot_pie_with_label)

# 创建单独的统一图例
legend_plot <- ggplot(data_processed, aes(fill = Category)) +
  geom_bar(show.legend = TRUE) +
  scale_fill_manual(values = c("A" = "#1f77b4", "B" = "#ff7f0e", "C" = "#2ca02c")) +
  theme_void() +
  theme(legend.position = "right") +
  guides(fill = guide_legend(title = "分类"))

# 排列饼图矩阵,调整行列间距并整合图例
final_plot <- wrap_plots(plots_list, ncol = 20) +
  plot_layout(guides = "collect",  # 收集统一图例
              heights = rep(1, 18),  # 统一每行高度
              widths = rep(1, 20)) +  # 统一每列宽度
  plot_annotation(title = "饼图矩阵可视化",
                  subtitle = "替代常规热图展示多分类占比") +
  theme(plot.title = element_text(hjust = 0.5, size = 14),
        plot.subtitle = element_text(hjust = 0.5, size = 12))

# 合并图例与主图
final_plot + legend_plot + plot_layout(widths = c(10, 1))

3. 添加行列标题

通过grid包添加自定义行列标签,提升可读性:

library(grid)

# 生成X/Y轴标签文本
x_labels <- paste0("X", 1:20)
y_labels <- paste0("Y", 1:18)

# 给主图添加行列标签
final_plot_with_labels <- final_plot +
  # 添加X轴顶部标签
  annotation_custom(textGrob(paste(x_labels, collapse = "  "), 
                             gp = gpar(fontsize = 8)),
                    ymin = -0.1, ymax = -0.1, xmin = 0, xmax = 1) +
  # 添加Y轴左侧旋转标签
  annotation_custom(textGrob(paste(y_labels, collapse = "\n"), 
                             rot = 90, gp = gpar(fontsize = 8)),
                    xmin = -0.05, xmax = -0.05, ymin = 0, ymax = 1) +
  # 调整绘图区域边距,给标签预留空间
  theme(plot.margin = margin(10, 10, 20, 20, "mm"))

4. 其他优化点

  • 颜色一致性:提前定义分类颜色,避免ggplot自动分配颜色出现偏差
  • 性能优化:数据量较大时,优先使用dplyr+purrr的组合替代plyr::dlply,处理效率更高
  • 标注适配:如果饼图过小,可隐藏小占比分类的标注,避免重叠混乱

内容的提问来源于stack exchange,提问作者Charité Learner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:17:53