R 函数由 value 调用,而不是对事先调用 names() <- 的 data.table 的引用

r function called by value instead of reference on a data.table that had a names() <- call beforehand

提问人:MEcon 提问时间:5/31/2023 更新时间:5/31/2023 访问量:45

问:

我们知道有 4 种数据类型提供可变对象或按引用传递语义,并且是其中之一。(R 的最佳编码实践第 11 章Rdata.table)

在下面的一段代码中,首先我创建一个函数,该函数将向输入 data.table 添加一个变量。作为引用传递,这应该会更改发送到函数中的 data.table 并添加一列。 我创建了两个基本相同的 s,我用不同的方法将它们的列名更改为大写,然后将它们传递到函数中,但函数之后的对象并不相同!data.tabledata.table

library(data.table)


f <- function(x){
  x[,newvar:=2020]
}

dt1 <- data.table(a=1:20,b=21:40)
dt2 <- data.table(a=1:20,b=21:40)


names(dt1) <- toupper(names(dt1))
setnames(dt2,toupper(names(dt2)))

names(dt1)
class(dt1)
str(dt1)

names(dt2)
class(dt2)
str(dt2)

f(dt1)
f(dt2)


names(dt1)
names(dt2)

这两个对象现在不同了。 不包含 !dt1newvar

为什么?

r data.table 按引用传递

评论

2赞 Roland 5/31/2023
更改名称后结帐。 删除按引用添加列所需的过度分配。不要将它与 data.tables 一起使用。truelength(dt1); truelength(dt2)names<-
0赞 MEcon 5/31/2023
@Roland什么是超额分配,如何检查?对于这个特定的功能,我有一个,所以不用担心,但我希望能够检查其他功能并确定。改名后 truelength 的结果不同:2 和 1024!在这种情况下,这意味着什么?setnames
1赞 Roland 5/31/2023
过度分配意味着为内存分配的列数多于当前存在的列数。Data.tables 几乎总是被过度分配。您可以通过比较 和 的返回值来检查这一点。也许阅读.truelength(DT)length(DT)help("truelength")
0赞 MEcon 5/31/2023
我对此阅读更多内容,奇怪的是,data.table 包似乎导致了 data.table 消失的有用警告。当我重写它删除 x = shallow(x) 行时,它在 dt1 上给了我这个警告运行函数 f(在下一条评论中继续):names<-.data.table
1赞 MEcon 5/31/2023
在 '[.data.table'(x, , ':='(newvar, 2020)) 中:通过获取 data.table 的(浅)副本来检测并修复无效的 .internal.selfref,以便 := 可以通过引用添加此新列。在早些时候,这个 data.table 是由 R 复制的(或者是使用 structure() 或类似方法手动创建的)。避免使用 names<- 和 attr<-,它们在 R 中目前(很奇怪)可能会复制整个 data.table。请改用 set* 语法以避免复制:?set、?setnames 和 ?setattr。如果此消息没有帮助,请将您的用例报告给 data.table 问题跟踪器,以便修复根本原因,否则......

答: 暂无答案