2 回答

TA貢獻(xiàn)1829條經(jīng)驗 獲得超6個贊
是的,它是在R中使用的<-(或=或->)的副本。整體對象。您可以使用tracemem(DT)和.Internal(inspect(DT)),如下所示。這個data.table特征:=和set()通過引用將它們傳遞給任何對象。因此,如果該對象以前被復(fù)制(通過subas簽名)<-或顯式copy(DT))然后是通過引用修改的副本。
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..
注意,即使是a向量被復(fù)制(不同的十六進(jìn)制值表示向量的新副本),盡管a沒有改變。甚至整個b被復(fù)制,而不僅僅是更改需要更改的元素。對于大型數(shù)據(jù)來說,這是很重要的避免,以及為什么:=和set()被介紹給data.table.
現(xiàn)在,用我們的拷貝newDT我們可以參考修改:
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 ..
注意,所有3個十六進(jìn)制值(列點的向量,以及2列中的每一列)都保持不變。因此,它確實是通過引用而修改的,根本沒有副本。
或者,我們可以修改原始DT引用:
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..
這些十六進(jìn)制值與我們看到的原始值相同。DT上面。類型example(copy)有關(guān)更多示例,請使用tracemem以及與.的比較data.frame.
順便說一下,如果你tracemem(DT)然后DT[2,b:=600]你會看到一份報告。的前10行的副本。print方法可以。用invisible()或在函數(shù)或腳本中調(diào)用時,print方法不被調(diào)用。
所有這一切也適用于內(nèi)部功能;即,:=和set()不要在寫時復(fù)制,即使在函數(shù)中也是如此。如果需要修改本地副本,請調(diào)用x=copy(x)在函數(shù)開始的時候。但是,記住data.table適用于大數(shù)據(jù)(以及小數(shù)據(jù)的快速編程優(yōu)勢)。我們故意不想復(fù)制大對象(永遠(yuǎn))。因此,我們不需要考慮通常的3*工作記憶因素的經(jīng)驗法則。我們試著只需要一個列那么大的工作記憶(即工作記憶系數(shù)為1/nol,而不是3)。

TA貢獻(xiàn)2012條經(jīng)驗 獲得超12個贊
簡單總結(jié)一下。
<-
data.table
<-
DT[i,j]<-v
:=
set*
data.table
:=
set*
data.table
DT <- data.table(a=c(1,2), b=c(11,12))
DT2
DT
:
DT2 <- DT
DT2
DT
data.table
:=
:=
DT2 := DT # not what := is for, not defined, gives a nice error
:=
DT[3,"foo"] := newvalue # not like this
DT[3,foo:=newvalue] # like this
DT
new
DT <- DT[,new:=1L]
DT
DT <-
:=
DT
:=
f <- function(X){ X[,new2:=2L] return("something else")}f(DT) # will change DTDT2 <- DT f(DT) # will change both DT and DT2 (they're the same data object)
data.table
data.table
data.table
.
copy()
DT3 <- copy(DT) # rather than DT3 <- DTDT3[,new3:=3L] # now, this just changes DT3 because it's a copy, not DT too.
DT$new4 <- 1L # will make a copy so use :=attr(DT,"sorted") <- "a" # will make a copy use setattr()
.Internal(inspect(x))
:=
j
:=
[...]
:
DT[, newcol:=mean(x), by=group]
- 2 回答
- 0 關(guān)注
- 822 瀏覽
添加回答
舉報