微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

terra 栅格和副作用的重复

如何解决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 点:

  1. 异常行为。也许应该警告用户。

“在 R 语义中,对象是按值复制的。这意味着修改副本会保持原始对象完好无损。”:深度或惰性副本是 R (https://rlang.r-lib.org/reference/duplicate.html) 的基本规则。因此,用户必须清楚地知道 terra (r <- logo) 中的简单赋值不是按值复制,而是按引用复制,否则脚本中出错的风险很高。但是,目前 terra 的文档中没有解释这种异常行为。

  1. 浅拷贝更像是一种面向程序员的工具。

当用户理解 terra 副本是浅副本时,他们可能最喜欢制作深副本,因为 terra 用户使用浅副本可能受到限制且不常见。我没有看到太多这种行为有用的情况。深拷贝或惰性拷贝对于用户来说更为常见。

  1. 根据功能的异构行为

但这不是主要问题。主要问题在于,目前,某些操作会同时影响原始对象和复制对象,而其他操作则不会。 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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?