Ja, es ist die Unterzuweisung in R mit <-
(oder =
oder ->
), die eine Kopie des gesamten Objekts erstellt. Sie können dies mit tracemem(DT)
und .Internal(inspect(DT))
wie unten verfolgen . Die data.table
Funktionen :=
und set()
Zuweisung unter Bezugnahme auf das Objekt, an das sie übergeben werden. Wenn dieses Objekt zuvor kopiert wurde (durch eine Unterzuweisung <-
oder eine explizite Zuweisung copy(DT)
), wird die Kopie durch Referenz geändert.
DT <- data.table(a = c(1, 2), b = c(11, 12))
newDT <- DT
.Internal(inspect(DT))
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,12
# ATTRIB: # ..snip..
.Internal(inspect(newDT)) # precisely the same object at this point
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,12
# ATTRIB: # ..snip..
tracemem(newDT)
# [1] "<0x0000000003b7e2a0"
newDT$b[2] <- 200
# tracemem[0000000003B7E2A0 -> 00000000040ED948]:
# tracemem[00000000040ED948 -> 00000000040ED830]: .Call copy $<-.data.table $<-
.Internal(inspect(DT))
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),TR,ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,12
# ATTRIB: # ..snip..
.Internal(inspect(newDT))
# @0000000003D97A58 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040ED7F8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040ED8D8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,200
# ATTRIB: # ..snip..
Beachten Sie, wie sogar der a
Vektor kopiert wurde (ein anderer Hex-Wert zeigt eine neue Kopie des Vektors an), obwohl er a
nicht geändert wurde. Sogar das Ganze b
wurde kopiert, anstatt nur die Elemente zu ändern, die geändert werden müssen. Dies ist wichtig, um große Datenmengen zu vermeiden, und warum :=
und set()
wurden eingeführtdata.table
.
Jetzt newDT
können wir mit unserer Kopie es durch Bezugnahme ändern:
newDT
# a b
# [1,] 1 11
# [2,] 2 200
newDT[2, b := 400]
# a b # See FAQ 2.21 for why this prints newDT
# [1,] 1 11
# [2,] 2 400
.Internal(inspect(newDT))
# @0000000003D97A58 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040ED7F8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040ED8D8 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,400
# ATTRIB: # ..snip ..
Beachten Sie, dass alle 3 Hex-Werte (der Vektor der Spaltenpunkte und jede der 2 Spalten) unverändert bleiben. Es wurde also wirklich durch Referenz ohne Kopien modifiziert.
Oder wir können das Original DT
durch Bezugnahme ändern :
DT[2, b := 600]
# a b
# [1,] 1 11
# [2,] 2 600
.Internal(inspect(DT))
# @0000000003B7E2A0 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=2, tl=100)
# @00000000040C2288 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 1,2
# @00000000040C2250 14 REALSXP g0c2 [NAM(2)] (len=2, tl=0) 11,600
# ATTRIB: # ..snip..
Diese Hex-Werte sind die gleichen wie die ursprünglichen Werte, die wir DT
oben gesehen haben. Geben Sie example(copy)
für weitere Beispiele ein tracemem
und vergleichen Sie mit data.frame
.
Übrigens, wenn Sie tracemem(DT)
dann sehen DT[2,b:=600]
Sie eine Kopie gemeldet. Dies ist eine Kopie der ersten 10 Zeilen, die die print
Methode ausführt. Beim Umschließen mit invisible()
oder beim Aufrufen innerhalb einer Funktion oder eines Skripts wird dieprint
Methode nicht aufgerufen.
All dies gilt auch für Funktionen; dh :=
und set()
nicht beim Schreiben kopieren, auch nicht innerhalb von Funktionen. Wenn Sie eine lokale Kopie ändern müssen, rufen Sie x=copy(x)
zu Beginn der Funktion auf. Denken Sie jedoch daran, dass dies data.table
für große Datenmengen gilt (sowie für schnellere Programmiervorteile für kleine Datenmengen). Wir wollen absichtlich (nie) keine großen Objekte kopieren. Infolgedessen müssen wir die übliche Faustregel für den 3 * Arbeitsspeicherfaktor nicht berücksichtigen. Wir versuchen, nur Arbeitsspeicher zu benötigen, der so groß wie eine Spalte ist (dh einen Arbeitsspeicherfaktor von 1 / ncol anstelle von 3).
<-
anstelle der=
grundlegenden Zuweisung in R zu verwenden (z. B. von Google: google.github.io/styleguide/Rguide.xml#assignment ). Dies bedeutet jedoch, dass die Manipulation von data.table nicht wie die Manipulation von Datenrahmen funktioniert und daher weit davon entfernt ist, den Datenrahmen durch einen Drop-In zu ersetzen.