2013-04-08 20 views
5

Po to, aby wyczyścić niektóre rzeczy dla siebie, chciałbym lepiej zrozumieć, kiedy kopie są tworzone, a kiedy nie są w data.table. Ponieważ kwestia ta wskazuje, Understanding exactly when a data.table is a reference to (vs a copy of) another data.table, jeśli ktoś po prostu uruchamia następujące potem skończyć modyfikację oryginału:zrozumienie właściwości referencyjnych pliku data.table w R

library(data.table) 

DT <- data.table(a=c(1,2), b=c(11,12)) 
print(DT) 
#  a b 
# [1,] 1 11 
# [2,] 2 12 

newDT <- DT  # reference, not copy 
newDT[1, a := 100] # modify new DT 

print(DT)   # DT is modified too. 
#  a b 
# [1,] 100 11 
# [2,] 2 12 

Jednakże, jeśli ktoś to robi (na przykład), a następnie skończyć modyfikację nowej wersji:

DT = data.table(a=1:10) 
DT 
    a 
1: 1 
2: 2 
3: 3 
4: 4 
5: 5 
6: 6 
7: 7 
8: 8 
9: 9 
10: 10 

newDT = DT[a<11] 
newDT 
    a 
1: 1 
2: 2 
3: 3 
4: 4 
5: 5 
6: 6 
7: 7 
8: 8 
9: 9 
10: 10 

newDT[1:5,a:=0L] 

newDT 
    a 
1: 0 
2: 0 
3: 0 
4: 0 
5: 0 
6: 6 
7: 7 
8: 8 
9: 9 
10: 10 

DT 
    a 
1: 1 
2: 2 
3: 3 
4: 4 
5: 5 
6: 6 
7: 7 
8: 8 
9: 9 
10: 10 

jak rozumiem, powodem takiej sytuacji jest, ponieważ kiedy wykonać i oświadczenie, data.table zwraca zupełnie nowy stół w przeciwieństwie do odniesienia do pamięci zajmowanej przez wybranych elementów starego data.table. Czy to jest poprawne i prawdziwe?

EDIT: Przepraszam, że nie rozumie ij (zmiana ta powyżej)

+0

Nawet 'newDT <- DT [x <11]' utworzyłoby kopię. Do, 'newDT [, b: = 5]' po utworzeniu 'newDT' przez podzbiór. Użyj 'tracemem' i' .Internal (inspect (.)) 'Są narzędziami informacyjnymi do zrozumienia tego. – Arun

+0

@Arun: Przepraszam, nie jestem pewien, czy rozumiem twój punkt. Czy mógłbyś wyjaśnić, o czym mówisz? Czy chcesz powiedzieć, że pierwszy przykład zadziała tak samo jak drugi? w takim razie tak - to prawda. chciałem tylko osobnego przykładu, żeby wszystko wyjaśnić. – Alex

+0

z pewnością, czy możesz wyjaśnić, o której tu mowa: "J", o której tutaj mowa: "tak jak rozumiem, powodem tego jest to, że kiedy wykonujesz wyrażenie j", po prostu upewnij się. Napiszę odpowiedź, o której wtedy mówiłem. – Arun

Odpowiedz

7

Podczas tworzenia newDT W drugim przykładzie, jesteś oceny i (nie j). := przypisuje przez odniesienie w argumencie j. W instrukcji i nie ma odpowiedników, ponieważ samo odniesienie powoduje alokację kolumn, ale nie wierszy.

A data.table to lista. Ma długość == liczbę kolumn, ale jest ponad przydzielone więc można dodać więcej kolumn bez kopiowania całej tabeli (na przykład za pomocą := w j)

Jeśli skontrolować data.table, to możemy zobaczyć truelength (tl = 100) - to numbe słupa szczeliny wskaźnik

.Internal(inspect(DT)) 
@1427d6c8 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=1, tl=100) 
    @b249a30 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,... 

w data.table każdy element ma długość 10 i tl=0. Obecnie nie ma metody na zwiększenie liczby kolumn w celu dodania dodatkowych wierszy przez odniesienie.

Od ?truelength

Obecnie jest to po prostu lista wektor wskaźników kolumn czyli ponad przyznane (tj truelength (DT)), nie wektory kolumnowe same, co w przyszłości pozwoli szybki wiersz wstaw()

Podczas oceny i, data.table nie sprawdza, czy po prostu wrócił wszystkie wiersze w takiej samej kolejności jak w oryginale (i wtedy nie kopiować tylko w tym przypadku), to po prostu zwraca kopię .

+0

Doskonała odpowiedź, jak zwykle! Uratuję zażenowanie i odrzuć moją odpowiedź :). – Arun

+0

@mnel: Myślę, że nie było całkiem jasne z moim pytaniem lub nie do końca rozumiem twoją odpowiedź. Chciałem zrozumieć, czy podczas oceniania "i" kopia jest zwracana, a nie referencja. Czy to prawda? – Alex

+0

@Alex precyzyjnie - Przeformułowałem moje końcowe oświadczenie (które w drugim czytaniu nie było szczególnie jasne) – mnel