我想在移动窗口中使用一个简单的自定义函数。我过去曾为此成功使用过
terra::focal
,但现在遇到错误:
Error in as.vector(x, "character") : cannot coerce type 'closure' to vector of type 'character'
我不清楚为什么会这样。我可以在 SO 上找到的其他示例表明我在函数名称后缺少括号,但包括它们会返回不同的错误。
我不打算使用
terra::focal
;在同样快的矩阵上工作的替代方案也可以。这不是一个空间工作流程,所以我实际上更愿意避免将矩阵转换为 spatRaster
以使用 focal
然后再转换回来。
示例代码:
# Custom function: if mean of the window is greater than the threshold
# then return the value unchanged, otherwise return the minimum value in the window.
# (Returning value number 14, as this is the central cell in a 9 x 3 window)
mean.or.min <- function(x, ...){
if(mean(x) > 10) {
return(x[[14]])
} else {
x[[14]] <- min(x)
return(x[[14]])
}
}
# Create example data
set.seed(42)
temp.matrix <- matrix(data = sample(1:30, 600000, replace = TRUE), nrow = 200)
# Convert matrix to a spatRaster
temp.rast <- terra::rast(temp.matrix)
# Moving window
temp.rast.smoothed <- terra::focal(temp.rast, w = c(9,3), fun = mean.or.min, fillvalue = 0, expand = TRUE)
看起来像发出警告(但没有通过
cat()
发送到控制台,然后没有正确处理。见traceback()
输出的第4行:
Error in as.vector(x, "character") :
cannot coerce type 'closure' to vector of type 'character'
> traceback()
9: as.character.default(X[[i]], ...)
8: FUN(X[[i]], ...)
7: lapply(list(...), as.character)
6: .makeMessage(..., domain = domain)
5: warning("[", f, "] ", wmsg, ..., call. = FALSE)
4: warn(focal, "expand is ignored for non-standard functions")
3: .local(x, ...)
2: terra::focal(temp.rast, w = c(9, 3), fun = mean.or.min, fillvalue = 0,
expand = TRUE)
1: terra::focal(temp.rast, w = c(9, 3), fun = mean.or.min, fillvalue = 0,
expand = TRUE)
> mean.or.min <- function(x, ...){
+ if(mean(x) > 10) {
+ return(x[14])
+ } else {
+ x[14] <- min(x)
+ return(x[14])
+ }
+ }
> # Create example data
> set.seed(42)
> temp.matrix <- matrix(data = sample(1:30, 600000, replace = TRUE), nrow = 200)
>
> # Convert matrix to a spatRaster
> temp.rast <- terra::rast(temp.matrix)
>
> # Moving window
> temp.rast.smoothed <- terra::focal(temp.rast, w = c(9,3), fun = mean.or.min, fillvalue = 0)
> str(temp.rast.smoothed)
S4 class 'SpatRaster' [package "terra"]
正如 IFRTM 所指出的,这是由于警告处理不当造成的。警告应该是“对于不是‘内置’的函数,忽略扩展”。这已在开发版本 (1.7.33) 中修复。
您可以通过不使用
expand=TRUE
来解决它。以下对我有用。
# simplified function
mean.or.min <- function(x, ...){
if (mean(x) > 10) {
x[14]
} else {
min(x, ...)
}
}
library(terra)
set.seed(42)
temp.matrix <- matrix(data = sample(1:30, 60000, replace = TRUE), nrow = 200)
r <- terra::rast(temp.matrix)
x <- terra::focal(r, w=c(9,3), fun=mean.or.min, fillvalue=0)
你也可以这样做:
y <- ifel(focal(r, w=c(9,3), mean, fillvalue=0) > 10, r,
focal(r, w=c(9,3), min, fillvalue=0))
尽管这两次调用 focal,但速度要快得多,因为它使用内置函数“mean”和“min”而不是基于 R 的函数。