在R中是否有更快的方法对含NA的raster bricks求和?
问题
我有多个大型raster bricks需要求和,其中存在大量NA值:
- 默认的栅格直接相加(如
b1+b2+b3+b4)会因任意一个NA导致对应像元结果为NA,丢失大量有效数据 - 使用
sum(.., na.rm = TRUE)能得到预期结果,但处理大型数据时速度极慢
需要基于terra包的更优实现,类似base::Reduce的高效方法。
示例代码:
library(terra) # 创建4个带NA值的raster bricks set.seed(0) b1 <- rast(ncol=10, nrow=10, nlyr=5) values(b1) <- rnorm(size(b1), 1, 0.2) values(b1)[values(b1)<1] <- NA b2 <- rast(ncol=10, nrow=10, nlyr=5) values(b2) <- rnorm(size(b2), 1, 0.2) values(b2)[values(b2)<1] <- NA b3 <- rast(ncol=10, nrow=10, nlyr=5) values(b3) <- rnorm(size(b3), 1, 0.2) values(b3)[values(b3)<1] <- NA b4 <- rast(ncol=10, nrow=10, nlyr=5) values(b4) <- rnorm(size(b4), 1, 0.2) values(b4)[values(b4)<1] <- NA # 默认相加:存在NA的像元全部为NA b5 <- b1+b2+b3+b4 plot(b5) # 忽略NA求和:结果正确但速度极慢 b6 <- sum(b1,b2,b3,b4, na.rm = TRUE) plot(b6)
高效解决方案
以下是基于terra包的三种优化方法,均比原生sum(na.rm=TRUE)更快:
方法1:合并栅格后使用rowSums
terra::rowSums是针对多层栅格优化的向量化求和函数,底层实现高效,代码简洁:
# 合并所有bricks为一个多层栅格 combined <- c(b1, b2, b3, b4) # 计算每个像元的总和(忽略NA) b_fast_sum <- rowSums(combined, na.rm=TRUE) plot(b_fast_sum)
方法2:使用Reduce结合terra::add
适合内存有限的场景,通过逐步累加避免一次性加载所有数据到内存:
# 将bricks存入列表 brick_list <- list(b1, b2, b3, b4) # 用Reduce逐次累加,每次相加忽略NA b_reduce_sum <- Reduce(function(x, y) add(x, y, na.rm=TRUE), brick_list) plot(b_reduce_sum)
方法3:使用terra::app自定义求和
灵活度高,可扩展到其他自定义运算,同样是terra优化的向量化操作:
# 合并栅格后,对每个像元应用求和函数 b_app_sum <- app(combined, function(x) sum(x, na.rm=TRUE)) plot(b_app_sum)
为什么这些方法更快?
rowSums和app都是terra针对栅格数据优化的底层操作,减少了函数调用的额外开销Reduce结合add的方式分步骤处理数据,降低了内存占用,同时add是terra原生的高效运算函数
内容的提问来源于stack exchange,提问作者Blaiso
相关产品推荐
相关产品推荐

