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

ggplot面积图无法正确呈现数据问题求助

问题描述

从UN Comtrade获取并汇总贸易数据,自定义ns_eu_category字段划分世界区域。将各贸易部门数值转换为百分比后,用ggplot绘制面积图时出现异常:SITC Code 0(食品及活畜)类别出现无数据空白段,但单独绘制该类别的折线图显示其数值从未为0,其他区域也存在相同问题。

数据结构

> longterm_trade_data
# A tibble: 7,364 × 6
   ns_eu_category         year sitc_code import_or_export      value sector                                  
   <chr>                 <dbl> <chr>     <chr>                 <dbl> <chr>                                     
 1 East Asia and Pacific  1962 0         Export            946694358 Food And Live Animals                   
 2 East Asia and Pacific  1962 0         Import            745286120 Food And Live Animals                   
# ℹ 7,354 more rows

数据处理代码

trade_data_sector <- longterm_trade_data %>%
  group_by(ns_eu_category, year, import_or_export) %>%
  mutate(total_of_sectors = sum(value)) %>%
  ungroup() %>%
  drop_na() %>%
  mutate(percent = value / total_of_sectors)

面积图绘制代码

region <- "Sub-Saharan Africa"   
ix <- "Export"

trade_data_sector %>%
  mutate(truncated_name = sector %>% substr(0L, 10L),
         descriptor = paste0(sitc_code, ": ", truncated_name)) %>%
  filter(ns_eu_category == region, import_or_export == ix) %>%
  ggplot(aes(x = year, y = percent, fill = descriptor)) + 
  geom_area() +
  theme_minimal() + 
  labs(title = paste0(import_or_export, "s in ", region, " Over Time"), 
       caption = "Source: UN COMTRADE Database 1962-2023") +
  scale_y_continuous(breaks = seq(from = 0, to = 1, by = 0.1), labels = scales::percent, limits = c(0, 1)) +
  scale_x_discrete(limits = 1962:2023, expand = c(0,0)) +
  theme(
    axis.ticks.x=element_line(linewidth=0.2),
    axis.text.x = element_text(size = 6, family=my_font, angle=-90, vjust=0.5),
    axis.title.x = element_text(size = 8, family=my_font),
    axis.text.y=element_text(size = 6, family=my_font),
    axis.title.y = element_text(size = 8, family=my_font),
    panel.grid = element_blank(),
    legend.position="bottom",
    plot.title = element_text(size = 12, family=my_font),
    plot.subtitle = element_text(size = 10, family=my_font),
    legend.title = element_text( size=8, family=my_font),
    legend.text = element_text( size=8, family=my_font),
    strip.text = element_text(size=8, family=my_font),
    legend.key.size = unit(0.3, "cm"),
    plot.caption = element_text(size = 7, color="dark gray", family=my_font)
  )

单类别折线图代码

sector_code <- "0"

trade_data_sector %>%
  filter(ns_eu_category == region, import_or_export == ix, sitc_code == sector_code) %>%
  ggplot(aes(x = year, y = value)) +
  geom_line() +
  theme_minimal() +
  labs(title =  paste0(import_or_export, "s in ", region, " Over Time (Sector ", sector, ")"),
       caption = "Source: UN COMTRADE Database 1962-2023") +
  scale_x_discrete(limits = 1962:2022) +
  theme(
    panel.grid.major.y = element_line(color = "dark gray", linewidth = 0.1, linetype = "dashed"),
    axis.text.x = element_text(size = 6, family=my_font, angle=-90, vjust=0.5),
    axis.title.x = element_text(size = 8, family=my_font),
    axis.text.y=element_text(size = 6, family=my_font),
    axis.title.y = element_text(size = 8, family=my_font),
    panel.grid = element_blank(),
    legend.position="bottom",
    plot.title = element_text(size = 10, family=my_font),
    plot.subtitle = element_text(size = 8, family=my_font),
    legend.title = element_text( size=8, family=my_font),
    legend.text = element_text( size=8, family=my_font),
    strip.text = element_text(size=8, family=my_font),
    legend.key.size = unit(0.3, "cm"),
    plot.caption = element_text(size = 7, color="dark gray", family=my_font)
  )

排查与解决思路

1. 核心原因:缺失年份-部门的完整数据组合

geom_area要求每个年份下所有分组(即descriptor对应的部门)都存在数据,否则会出现空白断层。而原始数据中可能存在某年份下某个部门没有记录行的情况(并非value为0,而是数据缺失):

  • 折线图geom_line只需要该部门有数据的年份即可连线,因此不会显示空白;
  • 面积图需要所有部门在同一年份都有数据才能堆叠,缺失的部门会导致堆叠中断,出现空白。

2. 解决步骤

(1)补全所有数据组合

使用tidyr::complete()函数补全ns_eu_category、year、import_or_export、sitc_code的所有可能组合,缺失的value填充为0,确保每个年份每个部门都有数据:

library(tidyr)

trade_data_sector <- longterm_trade_data %>%
  # 补全所有维度的组合,缺失value填0
  complete(ns_eu_category, year, import_or_export, sitc_code, fill = list(value = 0)) %>%
  group_by(ns_eu_category, year, import_or_export) %>%
  mutate(total_of_sectors = sum(value)) %>%
  ungroup() %>%
  # 避免总贸易额为0时的除以0错误
  mutate(percent = ifelse(total_of_sectors == 0, 0, value / total_of_sectors))

(2)修正x轴的离散化设置

year字段是数值型(<dbl>),用scale_x_discrete会强制将其转为离散值,若数据中存在年份缺失,会导致x轴出现空白。改为使用scale_x_continuous更合适:

# 在面积图代码中替换x轴设置
scale_x_continuous(breaks = seq(1962, 2023, by = 5), limits = c(1962, 2023), expand = c(0,0))

(3)修复折线图的变量错误

单类别折线图的标题中使用了未定义的sector变量,应改为sector_code:

labs(title =  paste0(import_or_export, "s in ", region, " Over Time (Sector ", sector_code, ")"),
     caption = "Source: UN COMTRADE Database 1962-2023")

3. 验证逻辑

补全数据后,每个年份下所有部门都有对应的percent值(即使为0),geom_area可以正常堆叠,不会出现空白段;同时x轴使用连续型刻度,与year的数值类型匹配,避免离散化导致的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:09:50