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

如何使用饼图对比聚类与总体的分类变量分布?

实现聚类与总体分类变量相对频率的嵌套饼图(甜甜圈图)

我刚好做过类似的可视化需求,用嵌套饼图(也就是甜甜圈图)来对比聚类分组和总体人群的分类变量相对频率,确实能直观展现两者的分布差异。下面我就用你提供的示例数据,一步步实现这个效果。

方法一:提前整理频率数据(更清晰可控)

首先我们先把总体和聚类1的相对频率计算好,整理成适合绘图的格式,这样后续绘图逻辑更清晰:

# 加载需要的包
library(ggplot2)
library(dplyr)

# 你的示例数据集
mydf <- data.frame(week_day = as.factor(c(rep("monday",10), rep("monday",5), rep("tuesday",5))), 
                   cluster = c(rep(1,10), rep(2,10)))

# 计算总体人群的相对频率
overall_data <- mydf %>% 
  count(week_day) %>% 
  mutate(rel_freq = n / sum(n), group = "总体")

# 计算聚类1的相对频率
cluster1_data <- mydf %>% 
  filter(cluster == 1) %>% 
  count(week_day) %>% 
  mutate(rel_freq = n / sum(n), group = "聚类1")

# 合并数据,并为不同分组设置半径(区分内外层)
plot_data <- bind_rows(overall_data, cluster1_data) %>% 
  mutate(radius = ifelse(group == "总体", 0.5, 1))

接下来用ggplot绘制嵌套饼图:

ggplot(plot_data, aes(x = radius, y = rel_freq, fill = week_day)) +
  # 绘制环形条形图,width控制环的宽度
  geom_bar(stat = "identity", width = 0.5, color = "white") +
  # 转换为极坐标,得到饼图效果
  coord_polar("y", start = 0) +
  # 设置配色方案
  scale_fill_brewer(palette = "Set2") +
  # 添加标题和图例名称
  labs(title = "聚类1与总体人群week_day相对频率对比",
       fill = "星期") +
  # 调整主题,去掉冗余元素
  theme_minimal() +
  theme(axis.text = element_blank(),
        axis.title = element_blank(),
        panel.grid = element_blank(),
        legend.position = "bottom") +
  # 添加百分比标签,让数值更直观
  geom_text(aes(label = paste0(round(rel_freq*100, 1), "%")), 
            position = position_stack(vjust = 0.5))

方法二:直接在ggplot中计算相对频率(更简洁)

如果你不想提前整理数据,也可以直接在geom_bar里用(..count..)/sum(..count..)实时计算相对频率,分图层绘制内外饼图:

ggplot() +
  # 绘制内层:总体人群的相对频率分布
  geom_bar(data = mydf, aes(x = 0.5, y = (..count..)/sum(..count..), fill = week_day), 
           stat = "count", width = 0.5, color = "white") +
  # 绘制外层:聚类1的相对频率分布
  geom_bar(data = filter(mydf, cluster == 1), aes(x = 1, y = (..count..)/sum(..count..), fill = week_day), 
           stat = "count", width = 0.5, color = "white") +
  # 转换为极坐标
  coord_polar("y", start = 0) +
  scale_fill_brewer(palette = "Set2") +
  labs(title = "聚类1与总体人群week_day相对频率对比",
       fill = "星期") +
  theme_minimal() +
  theme(axis.text = element_blank(),
        axis.title = element_blank(),
        panel.grid = element_blank(),
        legend.position = "bottom") +
  # 手动添加百分比标签(需要用到之前计算好的频率数据)
  geom_text(data = overall_data, aes(x = 0.5, y = rel_freq, label = paste0(round(rel_freq*100,1), "%")),
            position = position_stack(vjust = 0.5)) +
  geom_text(data = cluster1_data, aes(x = 1, y = rel_freq, label = paste0(round(rel_freq*100,1), "%")),
            position = position_stack(vjust = 0.5))

关键细节说明

  • 我们通过设置不同的x值(radius)来区分内层(总体)和外层(聚类1),width参数控制环形的宽度,让内外层有明显区分。
  • 用coord_polar("y")把条形图转换成极坐标,就得到了嵌套饼图的效果。
  • 添加百分比标签可以让每个分类的相对频率一目了然,position_stack(vjust = 0.5)保证标签在每个扇形的中心位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:27:14