使用raster::calc自定义函数时遇错误的技术求助
问题描述
我生成了包含175个栅格的class.stack,每个栅格单元取值为0-3的整数或NA,且所有栅格的NA位置完全一致(代表未采样区域)。我需要基于该栅格栈计算一个新栅格:若0为多数类别则取0,否则取1-3的整数均值。
最初编写了如下自定义函数用于calc:
class.cond <- function(x){ if (sum(x == 0) > sum(x != 0)) {0} else {round(mean(x != 0))} }
了解到该函数无法正常运行,因为calc采用分块处理数据。随后尝试统计各类别的出现次数,代码如下:
count.zero <- calc(class.stack, na.rm=TRUE, fun=function(x){sum(x == 0)})
执行时出现错误:
Error in .calcTest(x[1:5], fun, na.rm, forcefun, forceapply) :
cannot use this function. Perhaps add '...' or 'na.rm' to the function arguments?
尝试通过忽略NA修改函数:
count.zero <- calc(class.stack, na.rm=TRUE, fun=function(x){ y <- as.numeric(na.omit(x)) sum(y == 0)})
但仍报相同错误。不过相同逻辑在向量测试中可正常运行:
test.vec <- c(NA, NA, 0, 0, 1, 2, 2, 3, 0, NA, 0, 1, 2) mod.vec <- as.numeric(na.omit(test.vec)) print(mod.vec) [1] 0 0 1 2 2 3 0 0 1 2 print(sum(mod.vec == 0)) [1] 4 print(sum(mod.vec == 2)) [1] 3
请问我哪里出错了?
问题原因与解决办法
报错的核心原因是:当你在calc中设置na.rm=TRUE时,这个参数会被传递给自定义函数,但你的函数并没有定义na.rm参数(也没通过...接收额外参数),导致calc无法完成参数传递,进而报错。
1. 修正统计0出现次数的代码
给自定义函数添加na.rm参数,或者用...接收额外参数,同时利用na.rm处理NA,不用手动na.omit:
# 方式1:显式定义na.rm参数 count.zero <- calc(class.stack, na.rm=TRUE, fun=function(x, na.rm){ sum(x == 0, na.rm = na.rm) }) # 方式2:用...接收额外参数 count.zero <- calc(class.stack, na.rm=TRUE, fun=function(x, ...){ sum(x == 0, ...) })
2. 直接完成最终需求的修正函数
写一个能处理NA、接收na.rm参数的函数,一次性实现你的需求:
class.cond <- function(x, na.rm = FALSE){ # 统计0的出现次数(忽略NA) n_zero <- sum(x == 0, na.rm = na.rm) # 统计1-3的出现次数(忽略NA) n_nonzero <- sum(x %in% 1:3, na.rm = na.rm) if(n_zero > n_nonzero){ return(0) } else { # 提取1-3的值,计算均值后取整 mean_val <- mean(x[x %in% 1:3], na.rm = na.rm) return(round(mean_val)) } } # 调用calc生成结果栅格 result_raster <- calc(class.stack, fun = class.cond, na.rm = TRUE)
补充说明
因为所有栅格的NA位置完全一致,na.rm=TRUE会自动忽略这些未采样区域,不需要手动na.omit,这样既符合calc的分块处理逻辑,效率也更高。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

