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

如何制作每个分面占比合计为100%的分面饼图?

问题描述

需要为数据集中的两个网络制作分面饼图,展示每个网络中2G、3G、4G类型的使用占比。但当前制作的图表中,所有分面的占比总和为100%,如何实现每个单独分面的占比合计为100%?

数据集来自BigQuery,表ID:bigquery-public-data.catalonian_mobile_coverage_eu.mobile_data_2015_2017,样本数据如下:

+   select(network, net, date)
     network net       date
1   Vodafone  3G 2015-01-05
2   Vodafone  3G 2015-01-05
3   Vodafone  3G 2015-01-05
4   Vodafone  3G 2015-01-05
5   Vodafone  3G 2015-01-05
6   Vodafone  3G 2015-01-05
7   Vodafone  3G 2015-01-05
8   Vodafone  3G 2015-01-05
9   Vodafone  3G 2015-01-05
10  Vodafone  3G 2015-01-05

当前使用的代码:

bigfi %>%
  drop_na(net) %>%
  filter(grepl("2015", date), net != "") %>%
  ggplot(aes(x="", fill = net)) +
  geom_bar(position="fill", color = "white") +
  facet_wrap(~network) +
  coord_polar(theta="y", start = 0) +
  theme_void() +
  geom_text(aes(label = after_stat(
    percent(ave(count, x, FUN = function(x) x / sum(x))))), 
    stat="count", position = "fill", color = "white", size=4) +
  labs(title = "Net Type Usage 2015") + 
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size=4))
解决方案

方法1:在ggplot中调整统计计算

问题出在ave(count, x, ...)只按x(空字符串)分组计算占比,导致全局汇总。需要把network加入分组变量,让占比按每个分面单独计算:

bigfi %>%
  drop_na(net) %>%
  filter(grepl("2015", date), net != "") %>%
  ggplot(aes(x="", fill = net)) +
  geom_bar(position="fill", color = "white") +
  facet_wrap(~network) +
  coord_polar(theta="y", start = 0) +
  theme_void() +
  # 修改ave的分组变量,加入network实现分面内单独计算占比
  geom_text(aes(label = after_stat(
    percent(ave(count, x, network, FUN = function(x) x / sum(x))))), 
    stat="count", position = position_fill(vjust = 0.5), color = "white", size=4) +
  labs(title = "Net Type Usage 2015") + 
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size=14)) # 修正原标题字号过小问题

方法2:先预处理数据(推荐,逻辑更清晰)

提前用dplyr计算每个network下各net的占比,把数据整理成适合绘图的格式,避免在ggplot中嵌套复杂计算:

library(dplyr)
library(ggplot2)
library(scales)

# 预处理数据:按network分组计算各net的占比
summary_data <- bigfi %>%
  drop_na(net) %>%
  filter(grepl("2015", date), net != "") %>%
  count(network, net) %>%
  group_by(network) %>%
  mutate(percent = n / sum(n),
         label = percent(percent)) %>%
  ungroup()

# 绘制分面饼图
ggplot(summary_data, aes(x="", y=percent, fill=net)) +
  geom_bar(stat="identity", position="fill", color="white") +
  geom_text(aes(label=label), position=position_fill(vjust=0.5), color="white", size=4) +
  facet_wrap(~network) +
  coord_polar(theta="y", start=0) +
  theme_void() +
  labs(title="Net Type Usage 2015") +
  theme(plot.title = element_text(hjust=0.5, face="bold", size=14))
说明
  • 方法1通过在ave函数中加入network分组变量,让统计计算限定在每个分面内部,确保每个network的饼图占比总和为100%。
  • 方法2提前整理数据,把占比计算逻辑从绘图代码中分离,更直观易懂,也方便后续调试修改。
  • 修正了原代码中标题字号size=4的问题,该字号过小几乎无法识别,调整为size=14。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 07:03:31