如何在terra中为各层因子水平不同的rast栈设置统一因子水平
问题描述
我有一个terra::rast()格式的连续数据栅格栈,需要将其分类为n个类别、转换为因子后进行离散尺度绘图。但遇到一个问题:当第一个栅格不包含其他栅格具备的全部因子(比如只含3个分类值,而非转换后的完整因子集合)时,绘图会异常。我希望能让栅格栈(或绘图函数)识别到:整个栈的因子水平是该栈的最小-最大值范围,部分层可能缺少部分水平。有意思的是,如果第一层包含所有可能的类别/因子,后续层的绘图就能正常显示。
# 模拟数据 library(terra) r1 <- rast(nrows = 10, ncols = 10, xmin = 0, xmax = 10, ymin = 0, ymax = 10) r1[] <- runif(ncell(r1), min = 1, max = 5) # 生成1到5之间的随机值 r2 <- rast(nrows = 10, ncols = 10, xmin = 0, xmax = 10, ymin = 0, ymax = 10) r2[] <- runif(ncell(r2), min = 1, max = 5) # 合并栅格为栈 s <- c(r1/r1, r1/r2, r2/r1, r2/r2) names(s) <- c("r1/r1", "r1/r2", "r2/r1", "r2/r2") # 重分类栅格栈 # 定义重分类矩阵 m_rc <- matrix(c(0, 0.5, 1, 0.5, 0.9, 2, 0.9, 1.1, 3, 1.1, 2, 4, 2, max(global(s, max, na.rm=T)$max), 5), ncol = 3, byrow = TRUE) # 应用重分类 s_r <- classify(s, m_rc) # 将重分类后的栅格转换为因子,用于分类绘图 s_r_f <- as.factor(s_r) # 使用ggplot2和tidyterra绘图,并自定义图例标签 ggplot() + geom_spatraster(data = s_r_f) + facet_wrap(~lyr, nrow = 2) + # 每层单独绘图 scale_fill_manual( values = c("blue","lightblue" , "white", "yellow", "red"), # 自定义颜色 na.value = "transparent", # NA值设为透明 ) + labs( title = "重分类栅格栈", labels = c("0 - 0.5","0.5 - 0.9","0.9 - 1.1","1.1 - 2","> 2"), fill = "类别" ) + theme_minimal()
解决方案
问题核心是as.factor(s_r)默认会为每个栅格层单独提取自身的唯一值作为因子水平,导致各层因子水平不统一。要解决这个问题,需要手动指定整个栅格栈的完整因子水平,确保所有层使用相同的因子定义:
- 统一因子水平:在转换为因子时,明确指定
levels参数为所有可能的分类值(即重分类后的1到5),同时绑定对应的标签:
# 定义完整的因子水平和对应标签 factor_levels <- 1:5 factor_labels <- c("0 - 0.5","0.5 - 0.9","0.9 - 1.1","1.1 - 2","> 2") # 转换为因子时强制使用统一的水平和标签 s_r_f <- as.factor(s_r, levels = factor_levels, labels = factor_labels)
- 调整绘图代码:此时因子本身已带有标签,
scale_fill_manual无需重复设置labels参数,直接使用统一的颜色映射即可:
ggplot() + geom_spatraster(data = s_r_f) + facet_wrap(~lyr, nrow = 2) + scale_fill_manual( values = c("blue","lightblue" , "white", "yellow", "red"), na.value = "transparent" ) + labs( title = "重分类栅格栈", fill = "类别" ) + theme_minimal()
这样处理后,即使部分栅格层缺少某些分类值,绘图时仍会保留完整的图例,所有层使用统一的颜色映射,彻底解决绘图异常问题。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

