간단히 조사한 결과 data.table
버그가있는 것 같습니다.
> DT = data.table(a=1:1e6,b=1:1e6,c=1:1e6,d=1:1e6)
> Rprofmem()
> sapply(DT,class)
a b c d
"integer" "integer" "integer" "integer"
> Rprofmem(NULL)
> noquote(readLines("Rprofmem.out"))
[1] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply"
[2] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply"
[3] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply"
[4] 4000040 :"as.list.data.table" "as.list" "lapply" "sapply"
> tracemem(DT)
> sapply(DT,class)
tracemem[000000000431A290 -> 00000000065D70D8]: as.list.data.table as.list lapply sapply
a b c d
"integer" "integer" "integer" "integer"
그래서, as.list.data.table
보고 :
> data.table:::as.list.data.table
function (x, ...)
{
ans <- unclass(x)
setattr(ans, "row.names", NULL)
setattr(ans, "sorted", NULL)
setattr(ans, ".internal.selfref", NULL)
ans
}
<environment: namespace:data.table>
>
참고 첫 번째 줄에 성가신 unclass
합니다. ?unclass
은 인수의 전체 복사본이 필요함을 확인합니다. 이 빠른 모양에서 sapply
또는 lapply
이 복사를하고있는 것처럼 보이지 않습니다. (R은 copy-on-write가 좋고 쓰기가 잘되지 않았기 때문에 생각하지 않았습니다.) as.list
은 lapply
입니다. (as.list.data.table
으로 파견).
따라서 unclass
을 피하면 속도가 빨라집니다. 의 시도하자
> DT = data.table(a=1:1e7,b=1:1e7,c=1:1e7,d=1:1e7)
> system.time(sapply(DT,class))
user system elapsed
0.28 0.06 0.35
> system.time(sapply(DT,class)) # repeat timing a few times and take minimum
user system elapsed
0.17 0.00 0.17
> system.time(sapply(DT,class))
user system elapsed
0.13 0.04 0.18
> system.time(sapply(DT,class))
user system elapsed
0.14 0.03 0.17
> assignInNamespace("as.list.data.table",function(x)x,"data.table")
> data.table:::as.list.data.table
function(x)x
> system.time(sapply(DT,class))
user system elapsed
0 0 0
> system.time(sapply(DT,class))
user system elapsed
0.01 0.00 0.02
> system.time(sapply(DT,class))
user system elapsed
0 0 0
> sapply(DT,class)
a b c d
"integer" "integer" "integer" "integer"
>
그래서, 그래, 무한 더 나은.
나도 이미 data.table
is()
list
때문에, as.list.data.table
방법을 제거 bug report #2000을 제기했습니다. 이것은 lapply(.SD,...)
과 같이 실제로 상당히 숙달 될 수 있습니다. [편집 : 이것은 v1.8.1에서 수정되었습니다.]
고마워요 !!
나는 잘 모르겠다. 왜 '사프리 (DT, 클래스)'가 아닌가? –
타이밍은 위의 텍스트에 추가 –
@MatthewDowle : 나는 OP가 sapply가 각 열에 대해 FUN으로 전달할 data.table의 하위 집합으로 임시 변수를 만드는 것을 의미한다고 생각합니다. 그것의 data.table은 정말로 크고 많은 컬럼을 가지고 있기 때문에 효율적이지 않습니다. 이런 이유로 그의 해결 방법은 data.table을 한 행으로 줄이고 먼저 sapply를 호출하는 것입니다. – digEmAll