Có một thời gian ngắn điều tra, và nó trông giống như một lỗi 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"
Vì vậy, nhìn vào 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>
>
Note pesky unclass
trên dòng đầu tiên. ?unclass
xác nhận rằng phải mất một bản sao sâu của đối số của nó. Từ cái nhìn nhanh này, có vẻ như không phải là sapply
hoặc lapply
đang thực hiện sao chép (tôi không nghĩ rằng họ đã làm từ R là tốt khi sao chép và viết), nhưng thay vào đó là as.list
trong lapply
(gửi đến as.list.data.table
).
Vì vậy, nếu chúng ta tránh unclass
, nó sẽ tăng tốc. Hãy thử:
> 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"
>
Vì vậy, vâng, vô tốt hơn.
Tôi đã tăng bug report #2000 để xóa phương thức as.list.data.table
, vì data.table
is()
cũng đã là list
. Điều này có thể tăng tốc một số thành ngữ thực sự, chẳng hạn như lapply(.SD,...)
. [EDIT: Điều này đã được sửa trong v1.8.1].
Cảm ơn bạn đã đặt câu hỏi này !!
Không chắc chắn tôi theo dõi. Tại sao không chỉ là 'sapply (DT, class)'? –
timings được thêm vào trong văn bản ở trên –
@MatthewDowle: Tôi nghĩ rằng OP có nghĩa là tạo ra các biến tạm thời với các tập con của data.table để chuyển đến FUN cho mỗi cột. Kể từ khi data.table của nó là thực sự lớn và có rất nhiều cột không hiệu quả. Vì lý do này, workaround của ông là để giảm data.table để một hàng đầu tiên, sau đó gọi sapply ... – digEmAll