В R, как я могу проверить, ссылаются ли два имени переменных на один и тот же базовый объект? - PullRequest
19 голосов
/ 07 сентября 2011

Например:

A <- 1:10
B <- A

И A, и B ссылаются на один и тот же базовый вектор.

Прежде чем я пашу и реализую что-то в C ... Есть ли функция в RМожно ли проверить, ссылаются ли две переменные на один и тот же базовый объект?

Спасибо.

Ответы [ 3 ]

17 голосов
/ 07 сентября 2011

Вы можете использовать функцию .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,...

Саймон Урбанек написал простой пакет с похожей функциональностью.Это называется ... подожди ... осмотри .Вы можете получить его с R-forge.net , запустив:

install.packages('inspect',repos='http://www.rforge.net/')

ОБНОВЛЕНИЕ: Предупреждение:

Я рекомендую использовать пакет Саймона, потому что яЯ не буду рекомендовать вам позвонить .Internal.Разумеется, он не предназначен для интерактивного использования, и вполне возможно, что он может привести к сбою сеанса R при его небрежном использовании.

16 голосов
/ 07 сентября 2011

Вы можете получить это через tracemem: если они указывают на одну и ту же ячейку памяти, это одни и те же объекты памяти.

> a = 1:10
> b = a
> tracemem(a)
[1] "<0x00000000083885e8"
> tracemem(b)
[1] "<0x00000000083885e8"
> b = 1:10
> tracemem(b)
[1] "<0x00000000082691d0"
> 

Что касается того, почему очень полезно знать, если ониявляются одними и теми же объектами: если они указывают на один и тот же объект и существует отложенная оценка / отложенная оценка / обещание, то, если один объект изменится, вычисления будут приостановлены, пока назначается новый блок памяти.В некоторых случаях задержка может быть существенной.Если есть большие объекты, то ожидание долго, пока большой блок памяти выделен и скопирован.В других случаях это может быть просто смертью от тысячи порезов: множество маленьких возмущений и задержек здесь и там.

Обновление (включая комментарий Джошуа): обязательно используйте untracemem(), чтобы не получить много выходных данных,Вы также можете посмотреть на retracemem, хотя я пока не могу прокомментировать его утилиту для настройки трассировки.

0 голосов
/ 07 августа 2018

Я нашел этот вопрос, когда искал функцию, которая проверяет, есть ли ссылка на одну переменную на всех , особенно в контексте 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

Создано в 2018-08-07 пакетом представлением (v0.2.0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...