#r #geospatial #terra
Вопрос:
Я недавно начал использовать terra
и должен поблагодарить разработчиков, это значительно облегчило мою жизнь при работе со многими большими растрами в R. Однако я столкнулся с незначительной проблемой, я sapp
пытаюсь применить focal
функцию к каждому слою в распылителе, focal
которую можно применять только к одному слою за раз.
С помощью небольшого воспроизводимого растрового изображения я могу запустить следующее в качестве примера желаемого результата:
library(terra)
packageVersion("terra")
>[1] ‘1.2.10’
s <- rast(system.file("ex/logo.tif", package="terra"))
s <- ifel(s == 255, 1, NA)
r1 <- terra::focal(s[[1]], w=3, fun = "any", na.only=TRUE)
r2 <- terra::focal(s[[2]], w=3, fun = "any", na.only=TRUE)
r3 <- terra::focal(s[[3]], w=3, fun = "any", na.only=TRUE)
r <- c(r1,r2,r3)
r
#class : SpatRaster
#dimensions : 77, 101, 3 (nrow, ncol, nlyr)
#resolution : 1, 1 (x, y)
#extent : 0, 101, 0, 77 (xmin, xmax, ymin, ymax)
#coord. ref. : proj=merc lon_0=0 k=1 x_0=0 y_0=0 datum=WGS84 units=m no_defs
#sources : memory
# memory
# memory
#names : red, green, blue
#min values : 0, 0, 0
#max values : 1, 1, 1
Когда я бегу sapp
за вышеуказанными воспроизводимыми данными, используя ту же грамматику, что и sapply
:
f1 <- sapp(s, fun = function(x){terra::focal(x = x, w = 3, fun = "any", na.only = TRUE)})
Я получаю:
Ошибка в h(simpleError(msg, вызов)) : ошибка при вычислении аргумента » x «при выборе метода для функции «rast»: неиспользуемый аргумент (wopt = wopt)
Если я попытаюсь:
f <- sapp(s, terra::focal, c(w= 3, fun = "any", na.only = TRUE))
f
Я получаю следующее:
#class : SpatRaster
#dimensions : 77, 101, 3 (nrow, ncol, nlyr)
#resolution : 1, 1 (x, y)
#extent : 0, 101, 0, 77 (xmin, xmax, ymin, ymax)
#coord. ref. : proj=merc lon_0=0 k=1 x_0=0 y_0=0 datum=WGS84 units=m no_defs
#source : memory
#names : red, green, blue
#min values : 0, 0, 0
#max values : 9, 9, 9
Обратите внимание на максимальные значения слоев. Как я могу настроить свой код, чтобы приложение работало по желанию?
Я могу получить желаемый результат с помощью sapply, но я предполагаю, что sapp будет гораздо эффективнее для больших данных, если я смогу заставить его работать.
f2 <- sapply(as.list(s), function(x){terra::focal(x = x, w= 3, fun = "any", na.only = TRUE)})
f2 <- rast(f2)
f2
#class : SpatRaster
#dimensions : 77, 101, 3 (nrow, ncol, nlyr)
#resolution : 1, 1 (x, y)
#extent : 0, 101, 0, 77 (xmin, xmax, ymin, ymax)
#coord. ref. : proj=merc lon_0=0 k=1 x_0=0 y_0=0 datum=WGS84 units=m no_defs
#sources : memory
memory
memory
#names : red, green, blue
#min values : 0, 0, 0
#max values : 1, 1, 1
Если кто-нибудь может оказать некоторую помощь, мы будем очень признательны 🙂
Ответ №1:
Я решил свою проблему.
Оказывается, вам нужно включить ...
аргумент в функцию, отправленную fun
таким образом:
s <- sapp(s, fun = function(x, ...) {focal(x, fun = "any", w = 3)})
Тогда это работает
Как выясняется sapp
, вызывает sapply внутренне и еще не реализовал распараллеливание, и несколько ядер не могут быть выделены, поэтому не так много улучшений в скорости по сравнению с app
тем, что реализует распараллеливание vs apply
.
Вот некоторые ориентиры, если какой-либо орган заинтересован…
terra::terraOptions(todisk = TRUE)
s <- rast(system.file("ex/logo.tif", package="terra"))
s <- terra::extend(s, c(500, 500))
s <- disaggregate(s, 10)
s <- terra::ifel(s == 255, 1, 0)
a <- function() {
s <- sapply(as.list(s), function(x){terra::focal(x = x, w= 3, fun = "any")})
s <- rast(s)}
b <- function(){
s <- sapp(s, fun = function(x,...) {focal(x, fun = "any", w = 3)})}
race <- microbenchmark::microbenchmark(
a(),
b(),
times = 5)
Результаты:
race
Unit: seconds
expr min lq mean median uq max neval cld
a() 63.32553 63.93399 65.03783 65.61699 65.73256 66.58011 5 a
b() 62.88114 63.85961 64.34571 64.16861 65.22703 65.59215 5 a