2012-05-14 50 views
8

Tôi muốn xác định các cột của một dữ liệu lớn.R: vòng qua các cột trong dữ liệu.table

colClasses <- sapply(DT, FUN=function(x)class(x)[1]) 

công trình, nhưng dường như các copy nội bộ được lưu trữ vào bộ nhớ:

> memory.size() 
[1] 687.59 
> colClasses <- sapply(DT, class) 
> memory.size() 
[1] 1346.21 

Một vòng lặp dường như không thể, bởi vì một data.table "với = FALSE" luôn luôn kết quả trong một data.table.

Một phương pháp nhanh chóng và rất bẩn là:

DT1 <- DT[1, ] 
colClasses <- sapply(DT1, FUN=function(x)class(x)[1]) 

cách elegent và hiệu quả nhất để làm điều này là gì?

+1

Không chắc chắn tôi theo dõi. Tại sao không chỉ là 'sapply (DT, class)'? –

+0

timings được thêm vào trong văn bản ở trên –

+3

@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

Trả lời

10

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, tốt hơn.

Tôi đã tăng bug report #2000 để xóa phương thức as.list.data.table, vì data.tableis() 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 !!

+0

Bài viết rất có nhiều thông tin. Cảm ơn bạn đã hiển thị các bước bạn đã sử dụng để gỡ lỗi này. –

+0

Cảm ơn Matthew! –

2

tôi không thấy bất cứ điều gì sai trong một cách tiếp cận như thế này

colClasses <- sapply(head(DT1,1), FUN=class) 

nó về cơ bản là giải pháp quick'n'dirty của bạn nhưng có lẽ rõ ràng hơn một chút (thậm chí nếu không muốn nói quá nhiều) ...

+0

Nó thực sự là một giải pháp tốt, nhưng không phải là thanh lịch như tôi hy vọng. –

+0

@ user1393348: vâng, nó vẫn là một giải pháp thay thế sau đây :) – digEmAll

Các vấn đề liên quan