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

R语言模拟人口数据集后绘制人口金字塔出现空图的问题排查

问题描述

我正在使用R语言学习人口金字塔绘制教程,但教程所需数据集已无法获取。我分析代码结构后模拟了如下格式的数据集:

Age = c("0-10", "0-10", "11-20", "11-20", "21-30", "21-30", "31-40", "31-40", "41-50", "41-50", "51-60", "51-60")
Gender = c("M", "F", "M", "F", "M", "F", "M", "F", "M", "F", "M", "F")
Value = as.integer(rnorm(12, 100,10))
vn_2018_pop = data.frame(Age, Gender, Value)

随后运行教程中的ggplot2绘图代码:

# Load some packages for scrapping data and data manipulation: 
library(rvest)
library(magrittr)
library(tidyverse)
library(extrafont)
my_colors <- c("#2E74C0", "#CB454A")
my_font <- "Roboto Condensed"
vn_2018_pop %>% ggplot(aes(Age, Value, fill = Gender)) + 
  geom_col(position = "stack") + 
  coord_flip() + 
  scale_y_continuous(breaks = seq(-5000000, 5000000, 1000000), 
                     limits = c(-5000000, 5000000), 
                     labels = c(paste0(seq(5, 0, -1), "M"), paste0(1:5, "M"))) + 
  theme_minimal() + 
  scale_fill_manual(values = my_colors, name = "", labels = c("Female", "Male")) + 
  guides(fill = guide_legend(reverse = TRUE)) + 
  theme(panel.grid.major.x = element_line(linetype = "dotted", size = 0.2, color = "grey40")) + 
  theme(panel.grid.major.y = element_blank()) + 
  theme(panel.grid.minor.y = element_blank()) + 
  theme(panel.grid.minor.x = element_blank()) + 
  theme(legend.position = "top") + 
  theme(plot.title = element_text(family = my_font, size = 28)) + 
  theme(plot.subtitle = element_text(family = my_font, size = 13, color = "gray40")) + 
  theme(plot.caption = element_text(family = my_font, size = 12, colour = "grey40", face = "italic")) + 
  theme(plot.margin = unit(c(1.2, 1.2, 1.2, 1.2), "cm")) + 
  theme(axis.text = element_text(size = 13, family = my_font)) + 
  theme(legend.text = element_text(size = 12, face = "bold", color = "grey30", family = my_font)) + 
  labs(x = NULL, y = NULL, 
       title = "Population Pyramids of Vietnam in 2018",
       subtitle = "A population pyramid illustrates the age-sex structure of a country's population and may provide insights about\npolitical and social stability, as well as economic development. Countries with young populations need to\ninvest more in schools, while countries with older populations need to invest more in the health sector.",
       caption = "Data Source: https://www.census.gov")

代码可正常运行,但生成了空图,请问我哪里出错了,该如何解决?

解决方案

空图的出现有两个核心问题,对应修改如下:

1. 数值范围严重不匹配

你模拟的Value数值在90-110左右,但代码中scale_y_continuous设置的y轴范围是-5000000到5000000,极小的数值在这个超大范围内会被压缩成几乎看不见的线条,导致空图。

2. 人口金字塔的核心逻辑缺失

教程中的原始数据集应该已经将男性人口数值转为负数(用于在y轴左侧显示),而你模拟的所有Value都是正数,再加上position = "stack",所有柱子会堆叠在y轴一侧,进一步导致无法正常显示。

修改后的完整代码

# 加载所需包
library(tidyverse)
library(extrafont)

# 模拟数据集
Age = c("0-10", "0-10", "11-20", "11-20", "21-30", "21-30", "31-40", "31-40", "41-50", "41-50", "51-60", "51-60")
Gender = c("M", "F", "M", "F", "M", "F", "M", "F", "M", "F", "M", "F")
Value = as.integer(rnorm(12, 100,10))
vn_2018_pop = data.frame(Age, Gender, Value)

# 关键修改:将男性数值转为负数
vn_2018_pop <- vn_2018_pop %>%
  mutate(Value = ifelse(Gender == "M", -Value, Value))

# 绘图代码(调整y轴范围和标签)
my_colors <- c("#2E74C0", "#CB454A")
my_font <- "Roboto Condensed"

vn_2018_pop %>% ggplot(aes(Age, Value, fill = Gender)) + 
  geom_col(position = "identity") +  # 改为identity,避免堆叠
  coord_flip() + 
  scale_y_continuous(breaks = seq(-120, 120, 20), 
                     limits = c(-120, 120), 
                     labels = abs(seq(-120, 120, 20))) +  # 显示绝对值,符合金字塔阅读习惯
  theme_minimal() + 
  scale_fill_manual(values = my_colors, name = "", labels = c("Female", "Male")) + 
  guides(fill = guide_legend(reverse = TRUE)) + 
  theme(panel.grid.major.x = element_line(linetype = "dotted", size = 0.2, color = "grey40")) + 
  theme(panel.grid.major.y = element_blank()) + 
  theme(panel.grid.minor.y = element_blank()) + 
  theme(panel.grid.minor.x = element_blank()) + 
  theme(legend.position = "top") + 
  theme(plot.title = element_text(family = my_font, size = 28)) + 
  theme(plot.subtitle = element_text(family = my_font, size = 13, color = "gray40")) + 
  theme(plot.caption = element_text(family = my_font, size = 12, colour = "grey40", face = "italic")) + 
  theme(plot.margin = unit(c(1.2, 1.2, 1.2, 1.2), "cm")) + 
  theme(axis.text = element_text(size = 13, family = my_font)) + 
  theme(legend.text = element_text(size = 12, face = "bold", color = "grey30", family = my_font)) + 
  labs(x = NULL, y = NULL, 
       title = "Population Pyramids of Vietnam in 2018",
       subtitle = "A population pyramid illustrates the age-sex structure of a country's population and may provide insights about\npolitical and social stability, as well as economic development. Countries with young populations need to\ninvest more in schools, while countries with older populations need to invest more in the health sector.",
       caption = "Data Source: Simulated Dataset")

修改说明

  • 数据处理:通过mutate将男性的Value转为负数,这是人口金字塔左右分栏的核心逻辑。
  • y轴调整:根据模拟数据的实际范围(-120到120)设置y轴刻度和范围,确保柱子能正常显示;同时用abs()让y轴标签显示绝对值,更符合人口金字塔的阅读习惯。
  • 位置参数:将geom_col的position改为identity,避免同一年龄段的男女柱子堆叠,保证左右分栏显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:25:25