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

使用ggplot2的coord_polar()绘制饼图异常,请求技术帮助

问题描述

有如下数据框,每行代表变量A-E,每列是观测值Obs1、Obs2,每个观测的变量值总和为1:

library(ggplot2)
library(dplyr)

test.df <- data.frame("Variable" = LETTERS[1:5], "Obs1"  = c(0.1, 0, 0.5, 0.2, 0.2), 
                      "Obs2" = c(0.3, 0.7, 0, 0, 0))

数据框内容:

> test.df
  Variable Obs1 Obs2
1        A  0.1  0.3
2        B  0.0  0.7
3        C  0.5  0.0
4        D  0.2  0.0
5        E  0.2  0.0

需求是为每个观测生成饼图(共2个),要求:

  • 图例显示所有变量且颜色统一
  • 0值仅在图例显示,不在饼图中

但使用以下代码时,生成的饼图中五个变量占比均等,不符合Obs1的数值:

ggplot(test.df, aes(x='', y='Obs1', fill = Variable)) + 
    geom_bar(width = 1, stat = 'identity') + coord_polar("y", start = 0)
解决步骤

1. 问题根源

代码里的y='Obs1'加了引号,会把Obs1当成字符串常量而非数据框的列名。ggplot会将每个变量的y值默认视为1,最终导致五个变量占比均等。

2. 正确实现方案

先将宽格式数据转为长格式,再通过分面生成两个饼图,同时强制保留所有变量的图例:

library(tidyr)

# 转换为长格式数据
test_long <- test.df %>% 
  pivot_longer(cols = starts_with("Obs"), names_to = "Observation", values_to = "Value")

# 绘制符合要求的饼图
ggplot(test_long, aes(x = "", y = Value, fill = Variable)) +
  geom_bar(width = 1, stat = "identity") +
  coord_polar("y", start = 0) +
  facet_wrap(~ Observation) + # 按观测值分面生成两个饼图
  scale_fill_discrete(drop = FALSE) + # 保留所有变量的图例(包括值为0的)
  theme_void() # 清理冗余的坐标轴和背景元素

关键说明

  • pivot_longer将宽格式数据转换为长格式,便于按观测值分组绘图
  • scale_fill_discrete(drop=FALSE)确保所有变量(即使在某观测中值为0)都保留在图例中,且颜色统一
  • 值为0的变量不会在对应饼图中显示,但图例中仍会保留其颜色标识

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:56:07