terra::focal 中的自定义函数出错

问题描述 投票:0回答:2

我想在移动窗口中使用一个简单的自定义函数。我过去曾为此成功使用过

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)


r moving-average terra
2个回答
1
投票

看起来像发出警告(但没有通过

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"]

0
投票

正如 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 的函数。

© www.soinside.com 2019 - 2024. All rights reserved.