Ya, subassignment di R menggunakan <-(atau =atau ->) yang membuat salinan seluruh objek. Anda dapat melacaknya menggunakan tracemem(DT)dan .Internal(inspect(DT)), seperti di bawah ini. The data.tablefitur :=dan set()menetapkan dengan mengacu apapun keberatan mereka berlalu. Jadi, jika objek itu sebelumnya disalin (oleh subassigning <-atau eksplisit copy(DT)) maka itu adalah salinan yang akan dimodifikasi oleh referensi.
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..
Perhatikan bagaimana bahkan avektor disalin (nilai heks yang berbeda menunjukkan salinan vektor baru), meskipun atidak diubah. Bahkan keseluruhan bsudah disalin, bukan hanya mengubah elemen yang perlu diubah. Itu penting untuk dihindari untuk data besar, dan mengapa :=dan set()diperkenalkan data.table.
Sekarang, dengan salinan newDTkami, kami dapat memodifikasinya dengan referensi:
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 ..
Perhatikan bahwa semua 3 nilai hex (vektor titik kolom, dan masing-masing dari 2 kolom) tetap tidak berubah. Jadi itu benar-benar dimodifikasi dengan referensi tanpa salinan sama sekali.
Atau, kita dapat memodifikasi yang asli DTdengan referensi:
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..
Nilai hex tersebut sama dengan nilai asli yang kami lihat di DTatas. Ketik example(copy)untuk lebih banyak contoh menggunakan tracememdan membandingkan data.frame.
Btw, jika Anda tracemem(DT)maka DT[2,b:=600]Anda akan melihat satu salinan dilaporkan. Itu adalah salinan dari 10 baris pertama yang dilakukan oleh printmetode ini. Ketika dibungkus dengan invisible()atau ketika dipanggil dalam suatu fungsi atau skrip, printmetode tersebut tidak dipanggil.
Semua ini berlaku di dalam fungsi juga; yaitu, :=dan set()jangan salin saat menulis, bahkan dalam fungsi. Jika Anda perlu memodifikasi salinan lokal, hubungi x=copy(x)di awal fungsi. Tetapi, yang diingat data.tableadalah untuk data besar (juga keunggulan pemrograman lebih cepat untuk data kecil). Kami sengaja tidak ingin menyalin objek besar (pernah). Akibatnya, kita tidak perlu mengizinkan aturan praktis faktor memori 3 * yang biasa digunakan. Kami mencoba hanya perlu memori yang bekerja sebesar satu kolom (yaitu faktor memori kerja 1 / ncol daripada 3).
<-alih-alih=untuk penugasan dasar di R (misalnya oleh Google: google.github.io/styleguide/Rguide.xml#assignment ). Tetapi ini berarti bahwa manipulasi data.tabel tidak akan berfungsi dengan cara yang sama seperti manipulasi bingkai data dan karenanya jauh dari penggantian drop-in ke bingkai data.