Evet, tüm nesnenin bir kopyasını oluşturan <-
(veya =
veya ->
) kullanarak R'de alt atamadır . Bunu ve öğelerini aşağıdaki gibi kullanarak izleyebilirsiniz . Özellikleri ve ne olursa olsun referans alınarak atama onlar geçirilen nesne. Bu nesne daha önce kopyalanmışsa (bir alt atama veya açık bir şekilde ), referans ile değiştirilen kopyadır.tracemem(DT)
.Internal(inspect(DT))
data.table
:=
set()
<-
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
Vektörün nasıl kopyalandığına (farklı onaltılık değer, vektörün yeni kopyasını gösterir), a
değiştirilmemiş olmasına rağmen dikkat edin . b
Sadece değiştirilmesi gereken unsurları değiştirmek yerine tamamı kopyalandı. Büyük verilerden kaçınmak ve neden :=
ve set()
bunlarla tanışmak önemlidir data.table
.
Şimdi, kopyaladığımızla newDT
referans olarak değiştirebiliriz:
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 onaltılık değerin (sütun noktalarının vektörü ve 2 sütunun her birinin) değişmeden kaldığına dikkat edin. Böylece hiçbir kopya olmadan referans olarak gerçekten değiştirildi.
Ya da orijinali DT
referans ile değiştirebiliriz :
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..
Bu onaltılı değerler, DT
yukarıda gördüğümüz orijinal değerlerle aynıdır . Tip example(copy)
fazlası kullanılarak örnekler için tracemem
ve kıyasla data.frame
.
Btw, eğer tracemem(DT)
o zaman DT[2,b:=600]
göreceğiniz bir kopyası bildirdi. Bu, print
yöntemin yaptığı ilk 10 satırın bir kopyasıdır . Bir invisible()
işlev veya komut dosyası ile sarıldığında veya içinde çağrıldığında, print
yöntem çağrılmaz.
Bütün bunlar iç fonksiyonlar için de geçerlidir; yani :=
ve set()
işlevler dahilinde bile yazma üzerine kopyalamayın. Yerel bir kopyayı değiştirmeniz gerekirse x=copy(x)
, işlevin başlangıcında arayın . Ancak unutmayın data.table
, büyük veriler içindir (küçük veriler için daha hızlı programlama avantajlarının yanı sıra). Büyük nesneleri (şimdiye kadar) kasten kopyalamak istemiyoruz. Sonuç olarak, her zamanki 3 * çalışan bellek faktörü kuralına izin vermemiz gerekmez. Sadece bir sütun kadar büyük bir çalışma belleğine ihtiyacımız var (yani 3 yerine 1 / ncol çalışma belleği faktörü).
<-
yerine=
(örneğin Google tarafından: google.github.io/styleguide/Rguide.xml#assignment ) kullanmak için İnternet'te yaygın olarak savunulmaktadır . Ancak bu, data.table manipülasyonunun veri çerçevesi manipülasyonu ile aynı şekilde işlev görmeyeceği ve bu nedenle veri çerçevesinin değiştirilmesinden çok uzak olduğu anlamına gelir.