【问题标题】:In raster set NA to zero where other rasters has value in that cell在栅格中将 NA 设置为零,其中其他栅格在该单元格中具有值
【发布时间】:2018-06-28 04:03:43
【问题描述】:

我有 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

【问题讨论】:

  • 我对使用栅格不够熟悉,无法自信地创建示例“栅格对象”来测试代码。你能提供生成一些小栅格的 MWE 代码吗?例如,您的单元格有 314M 并不重要,代码在 10x10 栅格上的效果可能与在 17Kx17K 上一样好。
  • @r2evans 这段代码是否可以解决您的问题:library(raster) # load library; r &lt;- raster(nrow=5, ncol=5) # create empty raster; r &lt;- rnorm(length(r)) # assign random values to each cell; r[1:5] &lt;- NA # assign first row with NAhead(r) # 查看已创建栅格的几行`
  • 这是一个好的开始。我将它添加到您的问题中,将来只需自己添加它(cmets 通常在显示简单单行命令之外的代码方面很糟糕)。
  • 这是一个栅格,您说您正在将多个与一些相同、一些不同的NA 位置进行比较。您的示例数据确实应该是自给自足的,因此如果您需要栅格列表或单独的对象,则需要创建它们。
  • 您知道这种转换发生的频率吗?例如,无论生成什么技术将“some”NAs 替换为 0,您关于栅格变得 “内存无法处理的大” 的声明都将成为一个因素。也许这是您需要(1)一台更大的计算机的情况; (2) 对算法的更改可以巧妙地处理这些NAs,而无需填充稀疏矩阵;或 (3) 别的东西。

标签: r arcgis raster


【解决方案1】:

示例数据:

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[])] &lt;- 0 由于内存限制而无法工作。通过执行is.na(r[]),您可以创建一个包含所有值的向量,从而要求发生该问题。你可以试试r[is.na(r)] &lt;- 0

【讨论】:

    【解决方案2】:

    这是一个快速技巧,它通过所有提供的栅格替换不是 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
    

    这不一定解决您的稀疏矩阵变得太大的问题,但这几乎肯定比您问题中的全局 replace-all-NA 更好。

    【讨论】:

    • 谢谢。但是最后一个函数给了我错误:Error in (function (r, i) : unused argument (simplify = dots[[3]][[1]])。有什么遗漏吗。我现在已将功能粘贴在下面的评论中,并在您纠正我后删除。
    • 糟糕,我应该在发布之前对其进行测试...删除它,一切正常。 (这是对代码的测试后添加。不必要。)
    • 是的,我对答案投了赞成票(即接受)。但是谁对我原来的问题投了反对票?非常感谢你,伙计。
    • 无论谁投了反对票,你能告诉我为什么吗?只是想知道什么会更好(或者错误更少)。
    • 您能否编辑您的答案,以便我再次投票(只需在代码注释中输入任何单词)。我的电脑昨天挂了。我已接受答案并想再次投票。问候。
    猜你喜欢
    • 2013-04-22
    • 2012-10-29
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多