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

ggplot堆叠百分比柱状图绘制异常问题求助

堆叠百分比柱状图绘制错误求助

我能正常绘制普通堆叠柱状图,但将position参数从"stacked"改为"fill"后,得到了错误的图表:

错误图表

我使用的代码如下:

ggplot(dataset, aes(fill = family_role_recoded, x=country, y=family_role_recoded)) +  geom_bar(position="fill", stat="identity") 

以下是可复现示例数据集:

structure(list(country = c("Lebanon", "Algeria", "Iraq", "Jordan", 
"Morocco", "Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", 
"Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", 
"Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", 
"Lebanon", "Lebanon", "Lebanon"), urban_rural = structure(c(2L, 
2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L), levels = c("Rural", "Urban", 
"Refugee camp"), class = "factor"), age = c(41L, 36L, 33L, 26L, 
28L, 33L, 31L, 45L, 70L, 18L, 23L, 20L, 24L, 44L, 38L, 39L, 23L, 
45L, 26L, 54L, 26L, 22L, 33L, 62L, 18L), education = c("Preparatory/Basic", 
"Preparatory/Basic", "Secondary", "Elementary", "Mid-level diploma/professional or technical", 
"Secondary", "Elementary", "Elementary", "Elementary", "Secondary", 
"BA", "Secondary", "BA", "Preparatory/Basic", "Elementary", "BA", 
"Secondary", "BA", "Preparatory/Basic", "Secondary", "Secondary", 
"Preparatory/Basic", "Preparatory/Basic", "Preparatory/Basic", 
"Secondary"), family_role = structure(c(1L, 2L, 2L, 1L, 2L, 2L, 
2L, 3L, 2L, 3L, 2L, 3L, 1L, 3L, 2L, 3L, 3L, 2L, 2L, 4L, 2L, 2L, 
3L, 1L, 3L), levels = c("I strongly agree", "I agree", "I disagree", 
"I strongly disagree", "Don't know", "Refused to answer"), class = "factor"), 
    religious = structure(c(2L, 1L, 2L, 2L, 3L, 2L, 2L, 3L, 1L, 
    3L, 3L, 1L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    3L), levels = c("Religious", "Somewhat religious", "Not religious"
    ), class = "factor"), gender = c("Male", "Female", "Female", 
    "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Female", 
    "Male", "Male", "Female", "Male", "Female", "Female", "Male", 
    "Female", "Female", "Male", "Male", "Male", "Female", "Male"
    ), education_cat = structure(c(2L, 2L, 3L, 2L, 3L, 3L, 2L, 
    2L, 2L, 3L, 4L, 3L, 4L, 2L, 2L, 4L, 3L, 4L, 2L, 3L, 3L, 2L, 
    2L, 2L, 3L), levels = c("No formal education", "Basic education", 
    "Secondary education", "Higher education"), class = "factor"), 
    family_role_recoded = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 
    2L, 1L, 2L, 1L), levels = c("Disagree/strongly disagree", 
    "Agree/strongly agree", "Don't know"), class = "factor")), row.names = c(NA, 
25L), class = "data.frame")

问题原因及解决方法

你的代码核心问题是将分类变量family_role_recoded映射给了y轴,同时使用stat="identity"。stat="identity"要求y轴是数值型数据,此时ggplot会把分类变量自动转换为底层的整数编码(比如1、2),导致计算出的比例完全错误,从而生成异常图表。

解法1:让ggplot自动统计计数(最简方式)

直接移除y参数和stat="identity"(geom_bar默认stat="count",会自动统计每个分组的数量),设置position="fill"即可生成百分比堆叠柱状图:

library(ggplot2)
ggplot(dataset, aes(x = country, fill = family_role_recoded)) +
  geom_bar(position = "fill") +
  scale_y_continuous(labels = scales::percent) # 可选:将y轴标签改为百分比格式

解法2:手动预处理数据(更灵活可控)

如果需要更清晰地控制统计逻辑,可以先用dplyr统计各分组的占比,再绘图:

library(ggplot2)
library(dplyr)

# 先统计每个国家下各family_role的数量及占比
summary_data <- dataset %>%
  count(country, family_role_recoded) %>%
  group_by(country) %>%
  mutate(percent = n / sum(n))

# 绘制堆叠百分比柱状图
ggplot(summary_data, aes(x = country, y = percent, fill = family_role_recoded)) +
  geom_col() + # geom_col对应stat="identity",适合已统计好的数据
  scale_y_continuous(labels = scales::percent)

两种方法都能生成正确的堆叠百分比柱状图,你可以根据需求选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:35:16