如何解决terra 栅格和副作用的重复
当修改一个重复的SpatRaster
的一些属性时,原来的也被修改了:
library(terra)
r <- rast(ncol=2,nrow=2,vals=c(5.3,7.1,3,1.2))
#class : SpatRaster
#dimensions : 2,2,1 (nrow,ncol,nlyr)
#resolution : 180,90 (x,y)
#extent : -180,180,-90,90 (xmin,xmax,ymin,ymax)
#coord. ref. : +proj=longlat +datum=wgs84 +no_defs
#source : memory
#name : lyr.1
#min value : 1.2
#max value : 7.1
xmin(r)
#[1] -180
t <- r # duplication
xmin(t) <- -300 # xmin modification of the duplicated SpatRaster
xmin(r) # the original SpatRaster has also been modified
#[1] -300
这是错误还是选择?它只发生在某些属性上,而不是全部。如果是选择,有什么方法可以创建“独立”副本,或者如何断开链接?
解决方法
发生这种情况是因为 SpatRaster 只是 C++ 对象的包装器。这使得 x
(下面)成为一个浅拷贝(即指向内存中的同一个对象)
library(terra)
r <- rast()
x <- r
仅在某些情况下,使用替换方法时才重要(您的示例不再受当前 terra
的影响)。我还添加了一个 copy
方法,该方法返回一个深拷贝,即指向不同(深拷贝)C++ 对象的 SpatRaster。
有关信息,函数 add
具有相同的问题(在 terra
1.0.11 中):
logo <- rast(system.file("ex/logo.tif",package="terra"))
nlyr(logo)
[1] 3
r <- logo
add(r) <- r[[1]]
nlyr(logo)
#[1] 4
,
这里可能存在误解,尤其是我的误解。正如您所指出的,add(r) <- r[[1]]
更改 r
是绝对正常的。但是它也改变 logo
的事实根本不是常规(add
函数应该向 r
添加一个层,而不是任何其他与当前脚本行无关的对象,根据文档)。
如果我理解正确的话,正如你之前解释的那样,这是因为 r <- logo
不会复制 logo
(深拷贝),而是只创建一个指向 logo
的指针(浅拷贝) .此选择对 terra
对象的使用具有重要影响,因为以后对 r
的修改也将修改 logo
对象(从用户的角度来看是“副作用”)。我在这里看到至少 3 点:
- 异常行为。也许应该警告用户。
“在 R 语义中,对象是按值复制的。这意味着修改副本会保持原始对象完好无损。”:深度或惰性副本是 R (https://rlang.r-lib.org/reference/duplicate.html) 的基本规则。因此,用户必须清楚地知道 terra
(r <- logo
) 中的简单赋值不是按值复制,而是按引用复制,否则脚本中出错的风险很高。但是,目前 terra
的文档中没有解释这种异常行为。
- 浅拷贝更像是一种面向程序员的工具。
当用户理解 terra
副本是浅副本时,他们可能最喜欢制作深副本,因为 terra
用户使用浅副本可能受到限制且不常见。我没有看到太多这种行为有用的情况。深拷贝或惰性拷贝对于用户来说更为常见。
- 根据功能的异构行为
但这不是主要问题。主要问题在于,目前,某些操作会同时影响原始对象和复制对象,而其他操作则不会。 add
修改了原始对象(副作用),但 res
不会改变它:
logo <- rast(system.file("ex/logo.tif",package="terra"))
nlyr(logo)
# [1] 3
res(logo)
# [1] 1 1
r <- logo
add(r) <- r[[1]]
nlyr(logo)
# side effect of add function on the number of layers
# [1] 4
res(r) <- c(10,10)
res(logo)
# no side effect of res function on the resolution
# [1] 1 1
如果所有这些猜想都是正确的,那么解释一下赋值后哪些函数会影响或不会影响原始对象,否则将无法可靠地编程。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。