在栅格中,将 NA 设置为零,其中其他栅格在该单元格中具有值

In raster set NA to zero where other rasters has value in that cell

我有 11 个包含大约 314578920 个像元的大栅格文件。其中一些细胞含有 NA。如果其他栅格在该特定单元格中具有值,我想将 NA 替换为零。但是所有栅格中包含 NA 的单元格应该是相同的。例如,见下图:

我创建了五个栅格(顶行)来说明我的问题(但实际上我有 11 个栅格)。输出栅格应该像底行栅格。

将所有 NA 替换为零(即,使用 r[is.na(r[])] <- 0)会使光栅太大以至于内存无法处理。或者,省略 NA 不符合我的目的。任何关于如何解决这个问题的想法都将受到高度赞赏。
示例代码:

library(raster)
r <- raster(nrow=5, ncol=5) # create empty raster
r[] <- rnorm(length(r))     # assign random values to each cell
r[1:5] <- NA                # assign first row with NA

这是一个快速技巧,可以替换所有提供的栅格中不属于 NANA 值。所有提供的栅格中任何 NA 的像元将保持 NA。 (顺便说一句,我假设所有栅格的大小都相同......)

我会做一些更简单的数据。我选择将它们存储在一个列表中,因为这使得这个解决方案更容易阅读(我认为),但也更容易扩展到你需要的尽可能多的栅格。

set.seed(2)
rs <- lapply(1:2, function(ign) {
  r <- raster(nrow=3, ncol=3)
  r[] <- sample(length(r))
  r
})

我将在此数据中创建两种类型的 NA:一种在两者中都存在(并且应该被忽略),另一种只在一个中(并且应该替换为 0):

rs[[1]][1:2] <- NA
rs[[2]][2] <- NA
lapply(rs, head)
# [[1]]
#    1  2 3
# 1 NA NA 5
# 2  9  7 4
# 3  1  8 3
# [[2]]
#   1  2 3
# 1 5 NA 2
# 2 8  1 7
# 3 3  4 6

栅格内部(您可能知道)只是 numeric 个矢量,因此我将映射每个矢量的索引 NA

nas <- lapply(rs, function(r) which(is.na(r[])))
nas
# [[1]]
# [1] 1 2
# [[2]]
# [1] 2

知道了这一点,我们就可以找到所有人共有的索引。可能有比这更简单的东西,但它有效(并且可读):

na_in_all <- Reduce(intersect, nas)
na_in_all
# [1] 2

现在我们只删除所有存在的所有索引:

nas <- lapply(nas, setdiff, na_in_all)
nas
# [[1]]
# [1] 1
# [[2]]
# integer(0)

现在我们只是重新迭代栅格和这个要替换的索引列表:

rs <- mapply(function(r,i) {
  if (length(i)) r[i] <- 0
  r
}, rs, nas)
head(rs[[1]])
#   1  2 3
# 1 0 NA 5
# 2 9  7 4
# 3 1  8 3
head(rs[[2]])
#   1  2 3
# 1 5 NA 2
# 2 8  1 7
# 3 3  4 6

这不一定能解决您的稀疏矩阵变得太大的问题,但这几乎肯定比您问题中的全局替换所有更好NA

示例数据:

library(raster)
r <- raster(nrow=5, ncol=5, vals=1:25)
set.seed(20181801)
s <- stack(lapply(1:5, function(i) {r[sample(25, 15)] <- NA; r}))

跨层计算 NA 个值

i <- sum(is.na(s))

重新分类,使所有像元值变为零,除非所有层都具有 NA

nl <- nlayers(s)
j <- reclassify(i, rbind(c(0, nl-1, 0), c(nl, nl ,NA)), right=NA)

使用 cover 在单元格中用零替换 NA 值,其中至少有一层具有值

z <- cover(s, j)

calc 的替代方法:

编写一个函数来对向量或矩阵执行您想要的操作:

f <- function(x) {
    i <- sum(is.na(x))
    if (i > 0 & i < 5) {
        x[is.na(x)] <- 0
    }
    x
}

zz <- calc(s, f)

在更直接的 R 习语中使用这些函数的一个重要原因是它们都是内存安全的。

顺便说一下,您提到 r[is.na(r[])] <- 0 由于内存限制而无法工作。通过执行 is.na(r[]),您创建了一个包含所有值的向量,从而要求该问题发生。您可以改为尝试 r[is.na(r)] <- 0.