减少大量栅格上镶嵌的内存使用

Mat*_*son 2 r r-raster

我正在使用包中的mosaic函数,raster使用@RobertH 在此处建议的方法来合并长长的栅格列表(11,000个文件)。

rlist <- sapply(list_names)
rlist$fun <- mean
rlist$na.rm <- TRUE
x <- do.call(mosaic, rlist)
Run Code Online (Sandbox Code Playgroud)

您可能会想到,这最终会超出我的可用内存(在几台不同的计算机和计算群集上)。我的问题是:有没有办法减少mosaicor 的内存使用量do.call?我试着改变maxmemoryrasterOptions(),但是这似乎并没有帮助呢。以较小的批次处理栅格似乎有问题,因为栅格在空间上可能是分离的(即,顺序栅格文件可能位于彼此之间很远的位置)。在此先感谢您提供的任何帮助。

mik*_*ntz 5

mosaic()您可以一次处理一个栅格,而不是一次将所有栅格(在调用中)加载到内存中吗?这样,每次将一个栅格添加到内存中时,您的镶嵌都会进行更新,但是您可以摆脱新栅格,而只需保持不断更新的镶嵌栅格即可。

假设您的rlist对象是栅格列表,我在想类似的东西:

伪码

  1. 初始化一个updating_raster对象作为列表中的第一个栅格
  2. 从第二个栅格开始,依次循环遍历列表中的每个栅格
  3. 将第i个栅格读入内存,称为 next_raster
  4. updating_raster通过使用加权平均值将其自身与下一个栅格进行镶嵌来覆盖对象来更新对象

R

使用mosaic()帮助文件示例中的代码进行测试...

首先生成一些栅格,然后使用标准镶嵌方法。

library(raster)

r <- raster(ncol=100, nrow=100)
r1 <- crop(r, extent(-10, 11, -10, 11))
r2 <- crop(r, extent(0, 20, 0, 20))
r3 <- crop(r, extent(9, 30, 9, 30))

r1[] <- 1:ncell(r1)
r2[] <- 1:ncell(r2)
r3[] <- 1:ncell(r3)

m1 <- mosaic(r1, r2, r3, fun=mean)
Run Code Online (Sandbox Code Playgroud)

将栅格放在列表中,以便它们与我认为的格式相似。

rlist <- list(r1, r2, r3)
Run Code Online (Sandbox Code Playgroud)

由于函数的NA处理weighted.mean(),我选择通过将求和和分解成不同的步骤来创建相同的效果...

首先初始化求和栅格:

updating_sum_raster <- rlist[[1]]
Run Code Online (Sandbox Code Playgroud)

然后初始化“计数器”栅格。这将表示在每个像素处镶嵌的栅格数量。在所有非的单元格中,它从1开始NA。它应该正确地处理NAs,使其仅在给定像素增加一个非NA值的情况下才递增。

updating_counter_raster <- updating_sum_raster
updating_counter_raster[!is.na(updating_counter_raster)] <- 1
Run Code Online (Sandbox Code Playgroud)

这是一个循环,不需要一次将所有栅格都存储在内存中。仅在不包含在其中的像元中,被添加到镶嵌的栅格的相对栅格的值为1 NA。通过将当前计数器栅格和更新计数器栅格相加来更新计数器。通过将当前栅格值与更新的栅格值相加来更新总和。

for (i in 2:length(rlist)) {

  next_sum_raster <- rlist[[i]]
  next_counter_raster <- next_sum_raster
  next_counter_raster[!is.na(next_counter_raster)] <- 1

  updating_sum_raster <- mosaic(x = updating_sum_raster, y = next_sum_raster, fun = sum)
  updating_counter_raster <- mosaic(updating_counter_raster, next_counter_raster, fun = sum)

}

m2 <- updating_sum_raster / updating_counter_raster
Run Code Online (Sandbox Code Playgroud)

这里的值似乎与mosaic()功能的使用相匹配

identical(values(m1), values(m2))
> TRUE
Run Code Online (Sandbox Code Playgroud)

但是栅格本身并不相同:

identical(m1, m2)
> FALSE
Run Code Online (Sandbox Code Playgroud)

不太确定为什么,但是也许这会使您更接近?

也许compareRaster()是一种更好的检查方法:

compareRaster(m1, m2)
> TRUE
Run Code Online (Sandbox Code Playgroud)

万岁!

这是情节!

plot(m1)
text(m1, digits = 2)
plot(m2)
text(m2, digits = 2)
Run Code Online (Sandbox Code Playgroud)

镶嵌函数和循环法之间的比较

多挖一点杂草...

mosaic.R文件:

mosaic()函数似乎初始化了一个名为的矩阵,v用于填充列表中所有栅格中所有像元的值。矩阵中的行v数是输出栅格中的像元数(基于完整的镶嵌范围和分辨率),列数是您要镶嵌的栅格数(11,000)。也许您会遇到R中矩阵创建的局限性?

使用1000 x 1000栅格(1e6像素),s 的v矩阵NA占用41 GB。您期望最终的镶嵌栅格有多大?

r <- raster(ncol=1e3, nrow=1e3)
x <- 11000
v <- matrix(NA, nrow=ncell(r), ncol=x)
format(object.size(v), units = "GB")
[1] "41 Gb"
Run Code Online (Sandbox Code Playgroud)