numero Perché data.table aggiorna i nomi(DT) per riferimento, anche se assegno ad un'altra variabile?



numero colonne r (1)

Aggiornamento: Questo è ora aggiunto nella documentazione per ?copy nella versione 1.9.3. Dalle NEWS :

  1. Sposta ?copy nella propria pagina di help e documenta che dt_names <- copy(names(DT)) è necessario per dt_names per non essere modificato come riferimento come risultato dell'aggiornamento di DT per riferimento (es: aggiungere una nuova colonna per riferimento) . Chiude #512 . Grazie a Zach per questa domanda SO e user1971988 per questa domanda SO .

Parte della tua prima domanda mi rende un po 'oscuro su cosa intendi per operatore <- (almeno nel contesto di data.table ), specialmente la parte: in altri casi, siamo esplicitamente avvisati che <- crea copie, sia di data.tables che di dataframes.

Quindi, prima di rispondere alla tua domanda, la tocco brevemente qui. Nel caso di un data.table un <- (assegnazione) semplicemente non è sufficiente per copiare un data.table . Per esempio:

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

Se vuoi creare una copy , devi menzionarla esplicitamente usando il comando copy .

DT2 <- copy(DT) # copied content to DT2
DT2[, z := 11:15] # only DT2 is affected

Da CauchyDistributedRV, capisco cosa intendi con i names(dt) <- . compiti names(dt) <- . ciò comporterà l'avvertimento. Lo lascerò come tale.

Ora, per rispondere alla tua prima domanda: sembra che names1 <- names(DT) si comportino allo stesso modo. Non ci avevo pensato / saputo fino ad ora. Il .Internal(inspect(.)) È molto utile qui:

.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"

Qui, si vede che stanno puntando alla stessa posizione di memoria @7fc86a851480 . Anche la truelength dei names1 è 100 (che per default è allocata in data.table , controlla ?alloc.col per questo).

truelength(names1)
# [1] 100

Quindi, in pratica, i names1 <- names(dt) sembrano accadere per riferimento. Cioè, names1 sta puntando alla stessa posizione del puntatore dei nomi delle colonne di dt.

Per rispondere alla seconda domanda: Il comando c(.) Sembra creare una copia poiché non vi è alcun controllo sul fatto che il risultato del contenuto a causa dell'operazione di concatenazione sia diverso . Cioè, dato che l'operazione c(.) Può cambiare il contenuto del vettore, ne risulta immediatamente una "copia" che viene eseguita senza verificare se i contenuti non sono modificati.

Ho memorizzato i nomi di un data.table come vector :

library(data.table)
set.seed(42)
DT <- data.table(x = runif(100), y = runif(100))
names1 <- names(DT)

Per quanto ne so, è un semplice vettore di caratteri di vaniglia:

str(names1)
# chr [1:2] "x" "y"

class(names1)
# [1] "character"

dput(names1)
# c("x", "y")

Tuttavia, questo non è un vettore di carattere ordinario. È un vettore di carattere magico! Quando aggiungo una nuova colonna al mio data.table , questo vettore viene aggiornato!

DT[ , z := runif(100)]
names1
# [1] "x" "y" "z"

So che questo ha qualcosa a che fare con come := aggiornamenti per incarico, ma questo mi sembra ancora magico, come mi aspetto <- per fare una copia dei nomi di data.table .

Posso risolvere il problema avvolgendo i nomi in 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"

La mia domanda è duplice:

  1. Perché names1 <- names(DT) crea una copia dei nomi di data.table ? In altri casi, siamo esplicitamente avvisati che <- crea copie, sia di data.table che di data.frame s.
  2. Qual è la differenza tra names1 <- names(DT) e names2 <- c(names(DT)) ?




data.table