如何在函数的输出列表中包含terra对象?

kkih6yb8  于 2023-09-27  发布在  其他
关注(0)|答案(1)|浏览(100)

我目前正在更新virtualspecies R包,从raster转移到terra
在这个包中,我曾经在函数的输出列表中从raster包中运送光栅。这些输出是一个简单的列表,带有一个名为virtualspecies的附加类,其中列表中的一到两个元素是RasterLayerRasterStack类的对象。
例如,下面是如何在这个包中创建一个输出对象,从这里开始:

results <- list(approach = "pca",
                  details = list(variables = sel.vars,
                                 pca = pca.object,
                                 rescale = rescale,
                                 axes = axes, 
                                 means = means,
                                 sds = sds),
                  suitab.raster = suitab.raster)
  class(results) <-  append("virtualspecies", class(results))

在这个例子中,suitab.rasterRasterLayer类的对象。
这些virtualspecies对象是函数工作流的一部分,其中下一个函数将从列表中获取光栅,进行新的计算,并经常将另一个光栅添加到输出列表中。这些对象可以通过例如saveRDS()并保持其功能。
要将此软件包从raster转换为terra,我的问题是:如何将terra对象合并到函数的简单输出列表中,以确保这些对象保持自包含,并且可以在不同的R会话或计算机之间轻松传输?

  • 请注意,我希望尽可能保持对象自包含,因为这是我们在paper中使用的参数之一,我们在其中引入了virtualspecies包:*

“生成的虚拟物种可存储在硬盘驱动器上,并在文章的在线补充材料中提供”
我目前正在考虑三种可能性:
1.使用terra包中的wrap()函数将spatRasters对象存储在输出列表中。这可能意味着经常在包的函数之间 Package /展开对象。然而,据我所知(我只是从这方面开始),我可能需要使用proxy = FALSE来确保对象是自包含的和可移植的,这对于大型光栅或低内存计算机可能是有问题的。
1.使用writeRaster()并尝试跟踪栅格在输出列表中的保存位置。在这种情况下,对象将不再是独立的。此外,我不太愿意在磁盘上写入文件,因为我不太熟悉在包内执行此操作的最佳实践,以及如何确保对象可以跨操作系统移植,而不会为用户增加太多复杂性。
1.使用1的组合。和2.:使用wrap()作为首选方法,但当它不是内存安全的或简单地失败时,则使用writeRaster()并跟踪文件写入的位置,以便当函数需要访问光栅时,可以将对象重新读入R内存。
这些方法中的哪一种(或上面没有提到的一种)客观上是最好的,为什么?

vq8itlhq

vq8itlhq1#

现在我选择了解决方案#1,在输出列表中 Package terra对象,如下所示:

results <- list(approach = "pca",
                details = list(variables = sel.vars,
                               pca = pca.object,
                               rescale = rescale,
                               axes = axes, 
                               means = means,
                               sds = sds),
                suitab.raster = wrap(suitab.raster,
                                     proxy = FALSE))
class(results) <-  append("virtualspecies", class(results))

我还为$[[添加了通用函数,以便当用户想要访问光栅时,他们将获得未包裹的光栅,而不是包裹的光栅。
通过这样做,我也无意中使其余的代码更容易,因为我不必添加unwrap()每次我想访问一个光栅对象从这些列表之一。
下面是我如何添加这些泛型,以便在使用$[[访问时自动展开terra对象。

#' @export
#' @method `$` virtualspecies
`$.virtualspecies` <- function(x, name)
{
  if(inherits(as.list(x)[[name]], "PackedSpatRaster")) {
    return(unwrap(`[[`(as.list(x), name)))
  } else {
    return(`[[`(as.list(x), name))
  }
}

#' @export
#' @method `[[` virtualspecies
`[[.virtualspecies` <- function(x, name)
{
  if(inherits(as.list(x)[[name]], "PackedSpatRaster")) {
    return(unwrap(`[[`(as.list(x), name)))
  } else {
    return(`[[`(as.list(x), name))
  }
}

#' @export
#' @method `as.list` virtualspecies
as.list.virtualspecies <- function(x)
{
  class(x) <- "list"
  return(x)
}

这段代码可以工作,但我仍然不确定两个方面:
1.如果用户尝试wrap()非常大的栅格会发生什么?我还不知道如何处理这种情况。
1.我想知道我编写通用$[[函数的方式是否足够,并且在我尚未尝试的情况下不会导致问题。

相关问题