例如:
A <- 1:10
B <- A
A和B都引用相同的底层向量。
在我犁下并用C语言实现之前...... R中是否有一个函数可以测试两个变量是否引用相同的底层对象?
感谢。
答案 0 :(得分:17)
您可以使用.Internal
inspect
功能:
A <- 1:10
B <- A
.Internal(inspect(A))
# @27c0cc8 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,...
.Internal(inspect(B)) # same
# @27c0cc8 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,...
B[1] <- 21
.Internal(inspect(B)) # different
# @25a7528 14 REALSXP g0c6 [NAM(1)] (len=10, tl=150994944) 21,2,3,4,5,...
Simon Urbanek编写了一个具有类似功能的简单包。它被称为......等待它...... inspect。您可以通过运行:{/ p>从R-forge.net获取它
install.packages('inspect',repos='http://www.rforge.net/')
更新:警告:
我建议您使用Simon的套餐,因为我不打算建议您拨打.Internal
。它当然不打算以交互方式使用,并且很可能通过不小心使用它来使R会话崩溃。
答案 1 :(得分:16)
您可以通过tracemem
获取此信息:如果它们指向相同的内存位置,则它们是相同的内存对象。
> a = 1:10
> b = a
> tracemem(a)
[1] "<0x00000000083885e8"
> tracemem(b)
[1] "<0x00000000083885e8"
> b = 1:10
> tracemem(b)
[1] "<0x00000000082691d0"
>
至于为什么知道它们是否是相同的对象是非常有用的:如果它们指向同一个对象并且存在延迟评估/延迟评估/承诺,那么如果一个对象发生更改,则计算将在新的时候暂停分配内存块。在某些情况下,延迟可能很大。如果有大对象,则等待很长时间,同时分配和复制大块内存。其他时候它可能只是一千次削减造成的死亡:这里和那里有很多小扰动和延误。
更新(纳入约书亚的评论):请务必使用untracemem()
,以免获得大量输出。您也可以查看retracemem
,但我还不能评论其设置跟踪的实用程序。
答案 2 :(得分:0)
我在寻找一个功能来检查单个变量是否全部被引用 时发现了这个问题,尤其是在data.table的情况下。扩展其他答案,我相信以下功能可以做到这一点:
is_referenced <- function(x) {
nom <- as.character(substitute(x))
ls_ <- ls(parent.frame())
ls_ <- ls_[ls_ != nom]
tr <- tracemem(x)
for (i in ls_) {
if (identical(x, get(i, envir = parent.frame()))) {
if (identical(tr, tracemem(get(i, envir = parent.frame())))) {
untracemem(x)
untracemem(get(i, envir = parent.frame()))
print(i)
return(TRUE)
} else {
untracemem(get(i, envir = parent.frame()))
}
}
}
untracemem(x)
FALSE
}
x <- 1:10
y <- x
is_referenced(x)
#> [1] "y"
#> [1] TRUE
z <- 1:10
is_referenced(z)
#> [1] FALSE
y[1] <- 1L
is_referenced(y)
#> [1] FALSE
library(data.table)
DT <- data.table(x = 1)
ET <- DT
is_referenced(DT)
#> [1] "ET"
#> [1] TRUE
is_referenced(ET)
#> [1] "DT"
#> [1] TRUE
ET[, y := 1]
is_referenced(DT)
#> [1] "ET"
#> [1] TRUE
DT <- copy(ET)
is_referenced(DT)
#> [1] FALSE
由reprex package(v0.2.0)于2018-08-07创建。