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

如何在for循环中使用ggplot2?循环绘图报错排查

问题排查与修复方案

核心错误原因

报错Error: Discrete value supplied to continuous scale是因为给连续尺度参数传入了离散值,具体出在两处:

1. 栅格图层填充映射错误

geom_raster的aes(fill=paste0(variable, "_",scenario,"_",time_period,"_diff"))中,paste0生成的是字符串文本(例如"Bio4_ssp126_2041_2070_diff"),而非rona_df中对应的数值列。连续尺度的scale_fill_gradient无法处理离散字符串,引发冲突。

2. 散点大小映射错误

geom_point的aes(size = variable)中,variable是循环内的字符串(例如"Bio4"),属于离散值,但scale_size_continuous是连续尺度,两者不兼容。实际应该映射的是rona_data中对应variable的数值列,而非变量名本身。


修复后的代码

library(raster)
library(ggplot2)
library(rgdal)
library(sf)
library(broom)

#### 提前读取静态数据(放到循环外提升效率)
ammo_country <- readOGR("/data/personal2/sun/ammo/gf/chelsa2_crop_selected/current/ammo_extent_country.shp")
ammo_country_df <- broom::tidy(ammo_country, region="NAME_1")
cnames <- aggregate(cbind(long,lat)~id, data=ammo_country_df, FUN=mean)
range <- st_read("/data/personal2/sun/ammo/gf/ammo_binary.shp")

setwd("/data/personal2/sun/ammo/rona/")
variables <- c("Bio4", "Bio5", "Bio6", "Bio15", "Bio17")
scenarios <- c("ssp126", "ssp585")
time_periods <- c("2041_2070", "2071_2100")

for (variable in variables) {
  for (scenario in scenarios) {
    for (time_period in time_periods) {
      # 读取数据
      rona_data <- read.csv(paste0(scenario,"_",time_period,"_rona_xy.csv"), header=T, row.names=1)
      rona_layer <- raster(paste0(variable, "_",scenario,"_",time_period,"_diff.asc"))
      
      # 裁剪掩膜
      crop_layer2 <- crop(rona_layer, extent(range))
      crop_layer3 <- mask(crop_layer2, range)
      rona_df <- as.data.frame(as(crop_layer3, "SpatialPixelsDataFrame"))
      # 给栅格列重命名为固定名称,避免字符串映射问题
      colnames(rona_df)[3] <- "raster_value"
      
      # 绘图
      p <- ggplot() +
        geom_sf(data = range, color = "black", fill = NA, size = 0.7) +
        # 使用重命名后的列做填充映射
        geom_raster(data = rona_df, aes(x = x, y = y, fill = raster_value), alpha = 1) +
        # 用.data[[variable]]引用rona_data中对应的数值列
        geom_point(data = rona_data, aes(x = x, y = y, size = .data[[variable]]), 
                   color = "navy", alpha = 1, shape = 21, stroke = 1) +
        scale_fill_gradient(low = "lightblue", high = "blue", name = variable) +
        scale_size_continuous(limits=c(0,0.6), breaks=c(0.1,0.2,0.3,0.4,0.5)) +
        theme_bw() +
        theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
        labs(title = variable, x = "Lon", y = "Lat", size = "RONA") +
        # 使用tidy后的多边形数据,避免sf和sp对象混用问题
        geom_polygon(data=ammo_country_df, aes(x=long,y=lat,group=group), color="black", fill=NA) +
        geom_text(data=cnames, aes(x=long,y=lat,label=id), size=3)
      
      ggsave(paste0(time_period, "_",scenario,"_",variable,"_RONA.pdf"), plot=p, height=5.74, width=4)
    }
  }
}

额外优化点

  • 将静态空间数据(ammo_country、range)的读取放到循环外,避免重复IO操作,提升运行效率。
  • 把栅格数据列重命名为固定名称(例如"raster_value"),避免动态字符串映射的麻烦。
  • 使用broom::tidy后的ammo_country_df绘制多边形,避免sp对象和sf对象在ggplot中混用可能出现的兼容问题。
  • 合并重复的labs设置,让代码更简洁。

内容的提问来源于stack exchange,提问作者Pei-Wei Sun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 21:07:04