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

在R中制作动态人口金字塔时遇pivot_longer报错求助

R动态人口金字塔制作报错修复

运行制作动态人口金字塔的代码时,出现以下错误:

Error in pivot_longer():
! Can't select columns past the end.
ℹ Locations 2 and 3 don't exist.
ℹ There is only 1 column.
Run rlang::last_trace() to see where the error occurred.

错误原因

报错核心是pivot_longer(-c(1:3))试图排除前3列,但读取后的数据仅存在1列,说明数据读取环节出现问题:

  • 文件路径拼写错误,导致读取内容不符合预期
  • CSV文件分隔符不匹配(比如实际用分号分隔,但默认以逗号读取)
  • 下载的文件格式损坏或结构与预期不符

解决方案步骤

  1. 确认文件读取正确性
    • 用file.choose()手动选择文件,避免路径拼写错误
    • 读取后执行str(d)查看数据结构,确认是否包含year、gender、past.future及各年龄列
  2. 指定正确的分隔符
    • 如果CSV是分号分隔,给read.csv添加sep=";"参数
  3. 修正pivot_longer列选择逻辑
    • 确认前3列存在后,使用列名指定更稳妥:cols = -c(year, gender, past.future)

修正后的完整代码

library(dplyr)
library(tidyr)
library(stringr)
library(gganimate)

# 手动选择文件,避免路径错误
d <- read.csv(
  file.choose(),
  check.names = FALSE,
  sep = "," # 若文件为分号分隔,改为sep=";"
)

# 检查数据结构,确认列数符合预期
str(d)
head(d, n = 3)

# 数据整理:用列名指定排除项,避免列索引错误
d.tidy <- d %>% 
  as_tibble() %>% 
  pivot_longer(cols = -c(year, gender, past.future),
               values_to = "population", 
               names_to = "age")

# 调整人口数值:女性为负、男性为正,偏移中心横幅覆盖区域
d.tidy <- d.tidy %>% 
  mutate(population = ifelse(gender == "f", -population - 80, population + 80))

# 设置年龄因子顺序,保证金字塔按年龄排序
d.tidy$age <- factor(d.tidy$age, levels = colnames(d)[-c(1:3)])

# 计算性别间人口差异的最小值,用于高亮显示
d.tidy <- d.tidy %>% 
  group_by(year, age) %>%
  mutate(pop.min = min(abs(population)),
         pop.min = ifelse(gender == "m", pop.min, -pop.min)) %>%
  ungroup()

# 生成时间-性别分组,用于区分配色
d.tidy <- d.tidy %>% 
  mutate(time.gender = str_c(past.future, "_", gender))

my.colors <- c("past_m" = "steelblue4", "past_f" = "red4",
               "future_m" = "steelblue1", "future_f" = "red1")

# 基础金字塔绘图
p1 <- d.tidy %>% 
  ggplot(aes(x = age, y = population, fill = time.gender)) +
  geom_col(position = "identity", width = 1) +
  coord_flip(clip = "off") +
  scale_fill_manual(values = my.colors)

# 添加性别人口差异高亮层
p2 <- p1 + 
  geom_col(aes(y = pop.min), 
           fill = "white", alpha = .5, width = 1,
           position = "identity")  

# 添加中心横幅遮挡重叠区域
p3 <- p2 + 
  annotate(geom = "rect",
           xmin = -Inf, xmax = Inf, ymin = 80, ymax = -80,
           fill = "floralwhite")

# 在中心横幅添加年龄标签
p4 <- p3 +
  annotate(geom = "text",
           x = seq(0, 100, 5), y = 0, 
           label = seq(0, 100, 5),
           size = 3, fontface = "bold") 

# 调整坐标轴刻度与标题
breaks <- seq(0, 700, by = 100)
breaks.updated <- c(breaks + 80, -breaks - 80)

p5 <- p4 + 
  scale_y_continuous(
    breaks = breaks.updated,
    labels = function(x) {abs(x) - 80 }) + 
  labs(y = "女性(单位:千)                 男性(单位:千)   ",
       title = "模拟年份",
       subtitle = "{frame_time}") 

# 优化主题样式
p6 <- p5 + 
  theme_void() +
  theme(
    axis.text.x = element_text(size = 10, color = "snow4", margin = margin(t = 5)),
    axis.title.x = element_text(face = "bold", margin = margin(t = 5, b = 5)),
    plot.title = element_text(hjust = .1, vjust = -10, size = 10),
    plot.subtitle = element_text(hjust = .1, vjust = -6, face = "bold", size = 20),
    legend.position = "none")

# 创建年份过渡动画
p7 <- p6 + transition_time(time = year)
p7

# 保存动画(自动创建graphics文件夹)
dir.create("graphics", showWarnings = FALSE)
anim_save(filename = "Population pyramid animation.gif", 
          path = "graphics")

额外提示

  • 若运行str(d)后仍只有1列,打开下载的CSV文件检查表头、分隔符是否正确
  • 若文件为Excel格式,改用readxl::read_excel()读取更稳妥

内容的提问来源于stack exchange,提问作者Ana-Maria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 02:22:08