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.tables como dedata.frames. - ¿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ó
?copya su propia página de ayuda y documentó quedt_names <- copy(names(DT))es necesario para quedt_namesno se modifique por referencia como resultado de actualizarDTpor 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.