代码之家  ›  专栏  ›  技术社区  ›  89_Simple

规范化单个多边形的光栅

  •  0
  • 89_Simple  · 技术社区  · 3 年前
    library(raster)
    library(rnaturalearth)
    library(terra)
    
    r <- raster::getData('CMIP5', var='tmin', res=10, rcp=45, model='HE', year=70)
    r <- r[[1]]    
    shp <- rnaturalearth::ne_countries()
    
    newcrs <- "+proj=robin +datum=WGS84"
    
    r <- rast(r)
    shp <- vect(shp)
    r_pr <- terra::project(r, newcrs)            
    shp_pr <- terra::project(shp, newcrs)            
    

    对于 shp_pr ,我想规范化底层光栅 在0-1的范围内。这意味着将一个单元格除以一个国家边界内所有单元格的总和,并对所有国家重复此操作。我的做法如下:

    country_vec <- shp$sovereignt
    
    temp_ls <- list()
    
    for(c in seq_along(country_vec)){
      
      country_ref <- country_vec[c]
      
      if(country_ref == "Antarctica") { next }      
      
      shp_ct <- shp[shp$sovereignt == country_ref]
    
      r_country <- terra::crop(r, shp_ct) # crops to the extent of boundary 
      r_country <- terra::extract(r_country, shp_ct, xy=T) 
      r_country$score_norm <- r_country$he45tn701/sum(na.omit(r_country$he45tn701))
      r_country_norm_rast <- rasterFromXYZ(r_country[ , c("x","y","score_norm")])
      
      temp_ls[[c]] <- r_country_norm_rast
      
      rm(shp_ct, r_country, r_country_norm_rast)
      }    
    
    m <- do.call(merge, temp_ls)
    

    我想知道这是否是最有效/最正确的方法,即没有任何for循环,有人有任何建议吗?

    0 回复  |  直到 3 年前
        1
  •  1
  •   Robert Hijmans    3 年前

    一些更新和简化的示例数据(不需要投影数据)

    library(terra)
    library(geodata)
    r <- geodata::cmip6_world("HadGEM3-GC31-LL", "585", "2061-2080", "tmin", 10, ".")[[1]]
    v <- world(path=".")
    v$ID <- 1:nrow(v)
    

    解决方案

    z <- rasterize(v, r, "ID", touches=TRUE)    
    zmin <- zonal(r, z, min, na.rm=TRUE, as.raster=TRUE)
    zmax <- zonal(r, z, max, na.rm=TRUE, as.raster=TRUE)
    x <- (r - zmin) / (zmax - zmin)
    

    请注意,上面对0和1之间的每个国家的单元格值进行了归一化。

    要转换数据,使值加起来为1(按国家/地区),可以执行以下操作:

    z <- rasterize(v, r, "ID", touches=TRUE)    
    zsum <- zonal(r, z, sum, na.rm=TRUE, as.raster=TRUE)
    x <- r / zsum