source

data.table이 다른 data.table에 대한 참조(복사본)일 때 정확하게 이해

factcode 2023. 6. 13. 22:50
반응형

data.table이 다른 data.table에 대한 참조(복사본)일 때 정확하게 이해

참조별 특성을 이해하는 데 약간 어려움이 있습니다.data.table일부 작업은 참조를 '파기'하는 것으로 보이며, 정확히 무슨 일이 일어나고 있는지 알고 싶습니다.

생성 시data.table다른 곳에서data.table(을 통해)<-그런 다음 새 테이블을 업데이트합니다.:=원래 테이블도 변경됩니다.이는 다음과 같이 예상됩니다.

?data.table::copy스택 오버플로: 데이터 테이블 패키지의 참조별 전달

다음은 예입니다.

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

하지만, 만약 제가 비-:=사이의 기반 수정<-할당 및:=위의 선,DT이제 더 이상 수정되지 않음:

DT = data.table(a=c(1,2), b=c(11,12))
newDT <- DT        
newDT$b[2] <- 200  # new operation
newDT[1, a := 100]

print(DT)
#      a  b
# [1,] 1 11
# [2,] 2 12

그래서 그것은newDT$b[2] <- 200선은 어떻게든 참조를 '수정'합니다.이것이 어떻게든 복사본을 호출한다고 생각하지만, 저는 R이 이러한 작업을 어떻게 처리하고 있는지 완전히 이해하여 제 코드에 잠재적인 버그가 발생하지 않도록 하고 싶습니다.

누군가 저에게 이것을 설명해 주시면 대단히 감사하겠습니다.

예, Ring에서 하위 할당입니다.<-(또는)=또는->) 전체 개체의 복사본을 만듭니다.다음을 사용하여 추적할 수 있습니다.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벡터가 복사되었습니다(다른 16진수 값은 벡터의 새 복사본을 나타냅니다).a변경되지 않았습니다.심지어 전체.b변경해야 하는 요소만 변경하는 것이 아니라 복사한 것입니다.대용량 데이터의 경우 피해야 할 중요한 사항이며, 그 이유는:=그리고.set()에 소개되었습니다.data.table.

자, 우리의 복사된 것과 함께.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 ..

세 개의 16진수 값(열 점의 벡터 및 두 개의 각 열)은 모두 변경되지 않습니다.그래서 사본이 전혀 없이 참조에 의해 수정되었습니다.

또는 원본을 수정할 수 있습니다.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..

이러한 16진수 값은 우리가 본 원래 값과 동일합니다.DT위. 유형example(copy)자세한 예는 를 사용하여tracemem및 와의 비교data.frame.

그나저나, 만약 당신이tracemem(DT)그리고나서DT[2,b:=600]한 부가 보고되는 것을 볼 수 있습니다.그것은 처음 10개 행의 복사본입니다.print방법은 그렇습니다.로 시invisible() 함수나 때, 는함수또내호때출에될서트크스는또립,▁or,때될,print메서드가 호출되지 않았습니다.

이 모든 것은 함수 내부에서도 적용됩니다.:=그리고.set()함수 내에서도 쓰기 시 복사하지 마십시오.로컬 복사본을 수정해야 하는 경우, 다음으로 전화하십시오.x=copy(x)기능이 시작될 때.하지만, 기억하세요.data.table는 대용량 데이터를 위한 것입니다(소형 데이터를 위한 더 빠른 프로그래밍 이점도 있음).우리는 일부러 큰 물체를 복사하고 싶지 않습니다.따라서 일반적인 3* 작동 메모리 팩터 규칙을 고려할 필요가 없습니다.하나의 열만큼 큰 작업 메모리(즉, 3이 아닌 1/ncol의 작업 메모리 팩터)만 필요합니다.

간단히 요약하면 됩니다.

<-와 함께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

이것은 절대 복사하지 않으며 베이스에서도 복사하지 않습니다.두 이름R이 두 개다이의알른데수개있이표터체뿐시도입를다할니록름을▁(▁it뿐r▁marks▁just▁object입▁that)을 알 수 있도록 데이터 개체를 표시할 뿐입니다.DT2그리고.DT) 동일한 개체를 가리킵니다.따라서 R은 나중에 둘 중 하나가 하위 할당되면 개체를 복사해야 합니다.

에딱맞다니에 딱 .data.table. 그그. ▁too.:=그렇게 하기 위한 것이 아닙니다.인 오류입니다.:=이름을 것이 . : 체이름바것아이닙다니개는인하딩.

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]

RHS가 변경되었기 입니다.DT참고로엑스트라DT <-무엇을 오해하는 것입니다.:=쓸 수 은 불필요합니다. 거기에 쓸 수는 있지만, 불필요합니다.

DT됩니다.:=FUNCTION :EVEN FUNCTION :

f <- function(X){
    X[,new2:=2L]
    return("something else")
}
f(DT)   # will change DT

DT2 <- DT
f(DT)   # will change both DT and DT2 (they're the same data object)

data.table대규모 데이터셋을 위한 것입니다. 20GB가 있는경data.table기억 속에서 당신은 이것을 할 수 있는 방법이 필요합니다.이것은 매우 의도적인 설계 결정입니다.data.table.

물론 복사도 가능합니다.data에 data.table을 데이터셋을 만 하면 . data.table은 20GB 데이터셋을 복사할 수 있습니다.copy() 함수:

DT3 <- copy(DT)   # rather than DT3 <- DT
DT3[,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))구성 요소의 메모리 주소 값을 확인합니다(Matthew Dowle의 답변 참조).

:=j이와 같이 그룹별로 참조하여 하위 할당할 수 있습니다.그룹별로 참조하여 새 열을 추가할 수 있습니다.그래서 그런 거지.:=안에서 그런 식으로 행해집니다.[...]:

DT[, newcol:=mean(x), by=group]

언급URL : https://stackoverflow.com/questions/10225098/understanding-exactly-when-a-data-table-is-a-reference-to-vs-a-copy-of-another

반응형