在R中,如何检查两个变量名是否引用相同的底层对象?

时间:2011-09-06 22:22:24

标签: r

例如:

A <- 1:10
B <- A

A和B都引用相同的底层向量。

在我犁下并用C语言实现之前...... R中是否有一个函数可以测试两个变量是否引用相同的底层对象?

感谢。

3 个答案:

答案 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创建。