gpt4 book ai didi

r - 通过引用传递给函数时处理 R data.table 中的无效 selfref

转载 作者:行者123 更新时间:2023-12-03 14:30:36 28 4
gpt4 key购买 nike

我的小组使用 data.table 编写了大量代码,我们偶尔会被“通过获取整个表的副本检测到和修复的无效 .internal.selfref ...”警告而被咬。当数据表通过引用传递给函数时,这种行为可能会破坏我们的代码,而我正试图找出如何解决它。

假设我有一个函数将一列添加到 data.table 作为副作用 - 请注意原始 data.table 没有返回。

foo <- function(mydt){
mydt[, c := c("a", "b")]
return(123)
)

> x<- data.table(a=c(1,2), b=c(3,4))
> foo(x)
[1] 123
> x
a b c
1: 1 3 a
2: 2 4 b

x 已更新为新列。这是所需的行为。

现在假设发生了一些破坏 x 中内部自我引用的事情:
> x<- data.table(a=c(1,2), b=c(3,4))
> x[["a"]] <- c(7,8)
> foo(x)
[1] 123
Warning message:
In `[.data.table`(mydt, , `:=`(c, c("a", "b"))) :
Invalid .internal.selfref detected and fixed by taking a copy ...

> x
a b
1: 7 3
2: 8 4

我明白发生了什么(大部分)。 [["a"]] 结构不是 data.table 友好的; x 被转换为一个数据框,然后返回到一个数据表,这以某种方式搞乱了内部工作。然后在foo()内部,在添加列的引用操作中,检测到这个问题,并且做了一个mydt的拷贝;新列“c”已添加到 mydt。但是,该复制操作切断了 x 和 mydt 之间的传递引用关系,因此附加列不是 x 的一部分。

函数 foo() 将被不同的人使用,并且很难防止无效的内部 selfref 情况。外面的人可能很容易做一些像 x[["a"]] 这样会导致无效输入的事情。我试图弄清楚如何从 foo 内部处理这个问题。

到目前为止,我有这个想法,在 foo() 的开头:
if(!data.table:::selfrefok(mydt)) stop("mydt is corrupt.")

这至少让我们有机会发现问题,但它对 foo() 的用户不是很友好,因为这些输入可能被破坏的方式可能非常不透明。理想情况下,我希望能够纠正损坏的输入并维护 foo() 所需的功能。但是我看不到如何,除非我重构我的代码,以便 foo 返回 mydt 并将其分配给调用范围内的 x,这是可能的,但并不理想。有任何想法吗?

最佳答案

你应该阅读整个警告......

然后你会注意到

At an earlier point, this data.table has been copied by R (or been created manually using structure() or similar). Avoid key<-, names<- and attr<- which in R currently (and oddly) may copy the whole data.table.


[[<-类似于 names<-attr<-因为它将创建一个副本。

可以确保by-reference行为是用substitute构造调用,然后在父框架中求值
foo <- function(x) {
l <- substitute(x[,c := 'a'], as.list(match.call())['x']);
eval.parent(l)
return(123)}

xx<- data.table(a=c(1,2), b=c(3,4))
xx[["a"]] <- c(7,8)
foo(xx)
# [1] 123
# Warning message: .....

# but it now works!
xx
# a b c
# 1: 7 3 a
# 2: 8 4 a

警告仍然存在,但该功能按需要工作。

关于r - 通过引用传递给函数时处理 R data.table 中的无效 selfref,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24792509/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com