tutorial - ¿Por qué data.table actualiza nombres(DT) por referencia, incluso si lo asigno a otra variable?
data.table r tutorial (1)
He almacenado los nombres de un data.table
como un vector
:
library(data.table)
set.seed(42)
DT <- data.table(x = runif(100), y = runif(100))
names1 <- names(DT)
Por lo que puedo decir, es un vector de carácter vainilla simple:
str(names1)
# chr [1:2] "x" "y"
class(names1)
# [1] "character"
dput(names1)
# c("x", "y")
Sin embargo, este no es un vector de caracteres ordinarios. ¡Es un vector de personaje mágico! ¡Cuando agrego una nueva columna a mi data.table
, este vector se actualiza!
DT[ , z := runif(100)]
names1
# [1] "x" "y" "z"
Sé que esto tiene algo que ver con cómo :=
actualizaciones por asignación, pero esto todavía me parece mágico, ya que espero <-
hacer una copia de los nombres de data.table
.
Puedo arreglar esto envolviendo los nombres en c()
:
library(data.table)
set.seed(42)
DT <- data.table(x = runif(100), y = runif(100))
names1 <- names(DT)
names2 <- c(names(DT))
all.equal(names1, names2)
# [1] TRUE
DT[ , z := runif(100)]
names1
# [1] "x" "y" "z"
names2
# [1] "x" "y"
Mi pregunta es doble:
- ¿Por qué los
names1 <- names(DT)
crean una copia de los nombres dedata.table
? En otros casos, se nos advierte explícitamente que<-
crea copias, tanto dedata.table
s como dedata.frame
s. - ¿Cuál es la diferencia entre
names1 <- names(DT)
ynames2 <- c(names(DT))
?
Actualización: ahora se agrega en la documentación para ?copy
en la versión 1.9.3. De NEWS :
- Se movió
?copy
a su propia página de ayuda y documentó quedt_names <- copy(names(DT))
es necesario para quedt_names
no se modifique por referencia como resultado de actualizarDT
por referencia (por ejemplo, agregar una nueva columna por referencia) . Cierra #512 . Gracias a Zach por esta pregunta y al usuario1971988 por esta pregunta .
Parte de tu primera pregunta me deja un poco claro en cuanto a lo que realmente quieres decir con <-
operator (al menos en el contexto de data.table
), especialmente la parte: en otras instancias, se nos advierte explícitamente que <- crea copias, tanto de data.tables como de data.frames.
Entonces, antes de responder a su pregunta real, la tocaré brevemente aquí. En el caso de una data.table
una <-
(asignación) simplemente no es suficiente para copiar una data.table
. Por ejemplo:
DT <- data.table(x = 1:5, y= 6:10)
# assign DT2 to DT
DT2 <- DT # assign by reference, no copy taken.
DT2[, z := 11:15]
# DT will also have the z column
Si desea crear una copy
, debe mencionarla explícitamente utilizando el comando de copy
.
DT2 <- copy(DT) # copied content to DT2
DT2[, z := 11:15] # only DT2 is affected
Desde CauchyDistributedRV, entiendo lo que quieres decir con los names(dt) <- .
las asignaciones names(dt) <- .
eso dará lugar a la advertencia. Lo dejo como tal.
Ahora, para responder a su primera pregunta: Parece que names1 <- names(DT)
también se comporta de manera similar. No había pensado / sabido sobre esto hasta ahora. El .Internal(inspect(.))
Es muy útil aquí:
.Internal(inspect(names1))
# @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100)
# @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x"
# @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y"
.Internal(inspect(names(DT)))
# @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100)
# @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x"
# @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y"
Aquí puede ver que apuntan a la misma ubicación de memoria @7fc86a851480
. Incluso la truelength
de los names1
es 100 (que se asigna por defecto en data.table
, verifique ?alloc.col
para esto).
truelength(names1)
# [1] 100
Entonces, básicamente, los names1 <- names(dt)
asignación1 names1 <- names(dt)
parecen suceder por referencia. Es decir, names1
apunta a la misma ubicación que el puntero de nombres de columna de dt.
Para responder a su segunda pregunta: El comando c(.)
Parece crear una copia, ya que no se comprueba si el resultado del contenido debido a la operación de concatenación es diferente . Es decir, debido a que la operación c(.)
Puede cambiar el contenido del vector, da como resultado inmediatamente que se realice una "copia" sin verificar si los contenidos están modificados.