r - R data.table 是否记录为通过引用作为参数传递?
问题描述
检查这个玩具代码:
> x <- data.table(a = 1:2)
> foo <- function(z) { z[, b:=3:4] }
> y <- foo(x)
> x[]
a b
1: 1 3
2: 2 4
似乎 data.table 是通过引用传递的。这是故意的吗?这有记录吗?我确实通读了文档,但找不到关于这种行为的提及。
我不是在询问 R 的文档化引用语义(在:=
和set***
其他一些中)。我在问是否应该通过引用作为函数参数传递 data.table 完整对象。
编辑:在@Oliver 的回答之后,这里有一些更奇怪的例子。
> dt<- data.table(a=1:2)
> attr(dt, ".internal.selfref")
<pointer: 0x564776a93e88>
> address(dt)
[1] "0x5647bc0f6c50"
>
> ff<-function(x) { x[, b:=3:4]; print(address(x)); print(attr(dt, ".internal.selfref")) }
> ff(dt)
[1] "0x5647bc0f6c50"
<pointer: 0x564776a93e88>
因此,不仅.internal.selfref
与调用者的 dt 副本相同,地址也是如此。它确实是同一个对象。(我认为)。
data.frames 的情况并非如此:
> df<- data.frame(a=1:2)
> address(df)
[1] "0x5647b39d21e8"
> ff<-function(x) { print(address(x)); x$b=3:4; print(address(x)) }
>
> ff(df)
[1] "0x5647b39d21e8"
[1] "0x5647ae24de78"
也许根本问题是常规的 data.table 操作不会触发 R 的 copy-on-modify 语义?
解决方案
我认为您感到惊讶的实际上是 R 行为,这就是为什么它没有具体记录在中的原因data.table
(也许无论如何都应该如此,因为其含义对data.table
.
您很惊讶传递给函数的对象具有相同的地址,但这对于base
R 也是一样的:
x = 1:10
address(x)
# [1] "0x7fb7d4b6c820"
(function(y) {print(address(y))})(x)
# [1] "0x7fb7d4b6c820"
在函数环境中复制的是指向. x
此外,对于base
R,父x
级是不可变的:
foo = function(y) {
print(address(y))
y[1L] = 2L
print(address(y))
}
foo(x)
# [1] "0x7fb7d4b6c820"
# [1] "0x7fb7d4e11d28"
也就是说,只要我们尝试编辑 y
,就会制作一份副本。这与引用计数有关——你可以看到 Luke Tierney 在这方面的一些工作,例如这个演示文稿
不同之data.table
处在于它data.table
启用了父对象的编辑权限——我想你知道这是一把双刃剑。
推荐阅读
- azure - ADF 直到块跳过属性发送邮件电子邮件通知
- json - 邮递员监视器的问题
- python - 我可以在没有 @file:/// 的情况下制作需求文件吗?我既不能下载所有的包,也不能在 Heroku 上部署
- arrays - Amazon S3 图像通过 java 中的 bytearray 下载并在 javascript 中转换为 base64 不同的值
- tailwind-css - 如何让 Tailwind 网格在 640 像素以下的移动设备上工作?
- ios - 如何防止使用 xcodebuild 归档操作剥离符号?
- arrays - 在 Numpy Array Python 中获取日期时间索引
- python - 如何阻止 Pandas 丢失 1 位 datetime2 精度?
- date - 如何使用 Talend 以这种格式“Tue Feb 23 00:00:00 EST 2021”解析字符串到日期
- databricks - 在 Databricks 笔记本错误中显示图像