【问题标题】:Scale raster cell in stack from -1 to 1 R将堆栈中的光栅单元从 -1 缩放到 1 R
【发布时间】:2018-09-17 03:55:19
【问题描述】:

我有一个包含 364 层的栅格堆栈,其中 NDVI 值的每日变化率。

如果正从 0 到 1,如果负从 -1 到 0,我想在每个单元格中缩放这些值。到目前为止,我只找到了一个在单层中缩放值的解决方案(参见此处:Replace specific value in each band of raster brick in R)和不是沿着多层物体的单元格。此外,在整个时间序列中,我有相当数量的 NA 单元格,我也不太确定如何处理这个事实。

我从前面提到的帖子中获取了代码,并试图让它解决我的问题:

norm <- function(x){-1+(x-min)*((1-(-1))/(max-min))}

for(j in 1:ncell(tif)){

 if(is.na(sum(tif[j]))){
  NULL
 } else {

 cat(paste("Currently processing layer:", j,"/",ncell(tif), "\n"))

 min <- cellStats(tif[j],'min')
 max <- cellStats(tif[j],'max')

#initialize cluster
#number of cores to use for clusterR function (max recommended: ncores - 1)
beginCluster(31)

#normalize
tif[j] <- clusterR(tif[j], calc, args=list(fun=norm), export=c('min',"max"))

#end cluster
endCluster()
}
}

我不太确定这是否会产生所需的输出。很感谢任何形式的帮助!

【问题讨论】:

    标签: r scale raster


    【解决方案1】:

    一些示例数据

    library(raster)
    r <- raster(ncol=10, nrow=10)
    s <- stack(lapply(1:5, function(i) setValues(r, runif(100, -1, 1))))
    # adding NAs
    s[[2]][sample(100, 25, TRUE)] <- NA
    

    对于缩放(或任何其他操作)按单元格(根据要求),您可以将calc 与适用于矢量的函数一起使用。例如:

    ff <- function(i) {
        p <- which(i >= 0)
        n <- which(i <= 0)
        # positive values
        if (length(p) > 0) {
            i[p] <- i[p] - min(i[p], na.rm=TRUE)
            i[p] <- i[p] / max(i[p])
        }
        # negative values
        if (length(n) > 0) {
            i[n] <- i[n] - max(i[n], na.rm=TRUE)
            i[n] <- i[n] / abs(min(i[n]))
        }
        i
    }
    

    测试一下

    ff(c(-.3, -.1, .1, .4, .8))
    #[1] -1.0000000  0.0000000  0.0000000  0.4285714  1.0000000
    ff(c(-.3, -.1, .1, .4, .8, NA))
    #[1] -1.0000000  0.0000000  0.0000000  0.4285714  1.0000000         NA
    ff(c(-2,-1))
    #[1] -1  0
    ff(c(NA, NA))
    #[1] NA NA
    

    并使用它

    z <- calc(s, ff)
    

    根据所有单元格值的最小值和最大值,查看以下内容以按层进行缩放(我首先认为这是所要求的)。请注意,我使用的函数将值从 -1 缩放到 1,但不是将最低正值和最高负值缩放为零。

    minv <- abs(cellStats(s,'min'))
    maxv <- cellStats(s,'max')
    
    f1 <- function(i, mn, mx) {
        j <- i < 0
        j[is.na(j)] <- TRUE
        i[j] <- i[j] / abs(mn)
        i[!j] <- i[!j] / mx
        i
    }
    
    ss <- list()
    for (i in 1:nlayers(s)) {
        ss[[i]] <- calc(s[[i]], fun=function(x) f1(x, minv[i], maxv[i]))
    }
    
    ss1 <- stack(ss)
    

    或者没有循环

    f2 <- function(x, mn, mx) {
        x <- t(x)
        i <- which(x > 0)
        i[is.na(i)] <- FALSE
        mxx <- x / mx
        x <- x / mn
        x[i] <- mxx[i]
        t(x)
    }
    
    ss2 <- calc(s, fun=function(x) f2(x, minv, maxv))
    

    作为参考,简单地在 0 和 1 之间进行缩放

    mnv <- cellStats(s,'min')
    mxv <- cellStats(s,'max')
    x <- (s - mnv) / (mxv - mnv)
    

    要获得介于 -1 和 1 之间的值,您可以这样做

    y <- 2 * (x - 1)
    

    但是这样以前的负值可以变成正值,反之亦然。

    有关其他类型的缩放,请参阅 ?raster::scale

    【讨论】:

    • 感谢您的出色回答!这几乎是我所需要的,但据我了解,此解决方案适用于每层的最小/最大值,我需要一个适用于每个单元的最小/最大值(一种局部最小值/最大值)的解决方案为了将每个单元格从 -1 缩放到 1,不是吗?
    • 好的,我错过了,因为您在代码中使用了 cellStats。
    猜你喜欢
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 2020-10-02
    • 1970-01-01
    • 2023-01-17
    相关资源
    最近更新 更多