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

为何terra::rast转换NLCD栅格时将数值型转为因子且类名变更?

NLCD栅格转SpatRaster后因子类型与类名匹配问题解决

问题描述

我需要将国家土地覆盖数据库(NLCD)栅格裁剪至流域边界矢量。部分流域使用mask步骤会生成空栅格,因此改用terra::rast将栅格转为SpatRaster,投影至矢量CRS后执行裁剪与掩膜操作,但遇到两个问题:

  • terra::rast将原数值型的NLCD ID转为因子型的NLCD Class;
  • 因子类名与pal_nlcd()生成的图例不一致(如原“Pasture/Hay”变为“Hay/Pasture”),导致left_join无法正常匹配,影响后续自定义重分类的土地利用占比计算。

解决方案

1. 核心思路:基于数值ID匹配,避免因子转换问题

terra::rast读取带属性表的栅格时默认会转成因子,且类名与pal_nlcd()的标准命名存在差异。最可靠的解决方式是保留原始数值ID,直接用ID做匹配,彻底规避类名字符串不一致的问题。

修改后的完整代码

library(streamstats) # devtools::install_github("markwh/streamstats")
library(FedData)
library(terra)
library(sf)
library(tidyverse)

# 创建自定义重分类图例(基于NLCD数值ID匹配)
legend <- pal_nlcd() %>%
  mutate(ID2 = c(1,2,3,3,3,3,2,4,4,4,4,4,5,5,2,2,6,7,8,8))
legend_2 <- data.frame(ID2 = unique(legend$ID2)) %>% 
  mutate(Class2 = c("Open Water", "Other", "Developed", "Forest", "Grassland", "Pasture/Hay", "Cultivated Crops", "Wetlands"))
legend <- left_join(legend, legend_2, by = 'ID2')

# 下载流域边界并转为sf格式
setTimeout(400)
ws1 <- delineateWatershed(xlocation = -73.65167, ylocation = 42.93556, crs = 4326, includeparameters = "false")
ws1_sp <- toSp(ws1, what = 'boundary')
ws1_sf <- st_as_sf(ws1_sp)

# 下载NLCD栅格数据
nlcd <- get_nlcd(template = ws1_sf, label = 'HUDSON RIVER AT STILLWATER NY', year = 2016)

# 转为SpatRaster时强制保留数值ID,不转因子
nlcd_rast <- rast(nlcd, factors = FALSE)
# 投影、裁剪、掩膜(使用terra原生函数替代raster包函数)
nlcd_rast <- project(nlcd_rast, crs(ws1_sf))
nlcd_rast <- crop(nlcd_rast, ext(ws1_sf))
nlcd_rast <- mask(nlcd_rast, ws1_sf)

# 计算重分类后的土地利用占比(基于数值ID匹配)
nlcd_df <- as.data.frame(nlcd_rast, xy = FALSE) %>%
  drop_na() %>%
  rename(ID = NLCD.Land.Cover.Class) %>%
  # 用数值ID匹配,彻底解决类名不一致问题
  left_join(., legend[,c(1,2,5,6)], by = c('ID'='ID')) %>%
  group_by(Class2) %>%
  summarise(n = n()) %>%
  mutate(pland = round(n / sum(n), 4)) %>%
  arrange(Class2) %>%
  dplyr::select(c(1,3)) %>%
  complete(., Class2 = unique(legend$Class2), fill = list(pland = NA))

关键修改点

  • rast(nlcd, factors=FALSE):强制保留原始数值型ID,避免自动转为因子;
  • 匹配逻辑从类名字符串改为数值ID:彻底规避类名表述差异的问题;
  • 替换raster::extent为terra::ext:保持terra包生态的一致性,减少跨包调用风险。

验证修改效果

# 验证ID仍为数值型
class(as.data.frame(nlcd_rast, xy = FALSE)$NLCD.Land.Cover.Class) # 输出应为numeric
# 查看匹配后的占比结果
head(nlcd_df)

streamstats包安装问题解决

若安装streamstats遇到报错,可按以下步骤操作:

# 步骤1 - 重启R
# Session->Restart R

# 步骤2 - 将Rtools添加到系统PATH
old_path <- Sys.getenv("PATH")
Sys.setenv(PATH = paste(old_path, "C:\\rtools40\\usr\\bin", sep = ";"))

# 重新安装包
devtools::install_github("markwh/streamstats")
library(streamstats)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:54:56