r

En R, ¿cómo puedo verificar si dos nombres de variables hacen referencia al mismo objeto subyacente?



(3)

Por ejemplo:

A <- 1:10 B <- A

Tanto A como B hacen referencia al mismo vector subyacente.

Antes de arrancar e implementar algo en C ... ¿Hay una función en R que pueda probar si dos variables hacen referencia al mismo objeto subyacente?

Gracias.


Encontré esta pregunta al buscar una función que verifica si se hace referencia a una sola variable, especialmente en el contexto de data.table . Extendiendo las otras respuestas, creo que la siguiente función hace esto:

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

Creado el 2018-08-07 por el paquete reprex (v0.2.0).


Puede acceder a esto a través de tracemem : si están apuntando a la misma ubicación de memoria, son los mismos objetos de memoria.

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

En cuanto a por qué es muy útil saber si son los mismos objetos: si están apuntando al mismo objeto y hay una evaluación retrasada / evaluación perezosa / promesa entonces, si un objeto cambia, los cálculos se suspenderán mientras un nuevo bloque de memoria es asignado. En algunos contextos el retraso puede ser sustancial. Si hay objetos grandes, la espera es larga mientras se asigna y copia un gran bloque de memoria. Otras veces podría ser una muerte por mil cortes: muchas pequeñas perturbaciones y retrasos aquí y allá.

Actualización (Incorporando el comentario de Joshua): Asegúrate de usar untracemem() , para que no obtengas mucha salida. También puede mirar retracemem , aunque todavía no puedo comentar sobre su utilidad para establecer el rastreo.


Puede utilizar la función de inspect .Internal :

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 ha escrito un paquete simple con una funcionalidad similar. Se llama ... espera ... inspect . Puedes obtenerlo desde R-forge.net ejecutando:

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

ACTUALIZACIÓN: Una advertencia:

Te recomiendo que uses el paquete de Simon porque no te recomendaré que llames .Internal . Ciertamente, no está diseñado para usarse de manera interactiva y es muy posible que se bloquee su sesión R usándola de manera descuidada.