2012-04-11 34 views
6

Sử dụng một data.table, đó sẽ là cách nhanh nhất để "quét" ra một thống kê trên một lựa chọn các cột?data.tables và chức năng quét

Bắt đầu với (phiên bản lớn hơn đáng kể của) DT

p <- 3 
DT <- data.table(id=c("A","B","C"),x1=c(10,20,30),x2=c(20,30,10)) 
DT.totals <- DT[, list(id,total = x1+x2) ] 

Tôi muốn để có được kết quả data.table sau đây bằng cách lập chỉ mục các cột mục tiêu (2: p) để bỏ qua phím:

id x1 x2 
[1,] A 0.33 0.67 
[2,] B 0.40 0.60 
[3,] C 0.75 0.25 

Trả lời

4

tôi tin rằng một cái gì đó gần như sau (trong đó sử dụng các chức năng set() tương đối mới) sẽ là nhanh nhất:

DT <- data.table(id = c("A","B","C"), x1 = c(10,20,30), x2 = c(20,30,10)) 
total <- DT[ , x1 + x2] 

rr <- seq_len(nrow(DT)) 
for(j in 2:3) set(DT, rr, j, DT[[j]]/total) 
DT 
#  id  x1  x2 
# [1,] A 0.3333333 0.6666667 
# [2,] B 0.4000000 0.6000000 
# [3,] C 0.7500000 0.2500000 

FWIW, các cuộc gọi đến set() có dạng như sau:

# set(x, i, j, value), where: 
#  x is a data.table 
#  i contains row indices 
#  j contains column indices 
#  value is the value to be assigned into the specified cells 

nghi ngờ của tôi về tốc độ tương đối điều này, so với các giải pháp khác, dựa trên đoạn này từ data.table's NEWS file, trong phần nói về những thay đổi trong phiên bản 1.8.0:

o New function set(DT,i,j,value) allows fast assignment to elements 
    of DT. Similar to := but avoids the overhead of [.data.table, so is 
    much faster inside a loop. Less flexible than :=, but as flexible 
    as matrix subassignment. Similar in spirit to setnames(), setcolorder(), 
    setkey() and setattr(); i.e., assigns by reference with no copy at all. 

     M = matrix(1,nrow=100000,ncol=100) 
     DF = as.data.frame(M) 
     DT = as.data.table(M) 
     system.time(for (i in 1:1000) DF[i,1L] <- i) # 591.000s 
     system.time(for (i in 1:1000) DT[i,V1:=i])  # 1.158s 
     system.time(for (i in 1:1000) M[i,1L] <- i) # 0.016s 
     system.time(for (i in 1:1000) set(DT,i,1L,i)) # 0.027s 
+0

Cảm ơn cho câu trả lời. Tôi đã nâng cấp lên data.table 1.8.0 và chạy thành công mã kiểm tra ở trên. Tôi nhận được một cảnh báo phức tạp (sẽ không phù hợp ở đây) về cưỡng chế để tăng gấp đôi khi cả tử số và mẫu số là cột nguyên từ data.tables. Tôi sẽ chỉnh sửa câu hỏi cho hiệu ứng đó. –

+0

Tôi đang gặp khó khăn trong việc chỉnh sửa hôm nay: Không có nguồn cấp dữ liệu dòng. Dù sao, đây là mã: cho (j trong 2: p) { bộ (dt, allrows, j, dt [[j]]/denom [[2]]) } và cho cả dt và denom, cột 2 thành p là số nguyên. Cảnh báo tôi nhận được là –

+0

"Thông báo cảnh báo: Trong bộ (dt, allrows, j, dt [[j]]/denom [[2]]): Buộc 'nhân đôi' RHS thành 'số nguyên' để khớp với loại cột Thay đổi cột mục tiêu thành 'double' trước (bằng cách tạo một chiều dài vector 'double' mới 16863 (nrows of entire table) và gán nó, tức là 'replace' column), hoặc ép buộc RHS thành 'integer '(ví dụ: 1L, NA_ [thực | số nguyên] _, như. *, v.v.) để làm cho ý định của bạn rõ ràng và cho tốc độ. Hoặc, đặt loại cột chính xác lên phía trước khi bạn tạo bảng và dính vào nó, xin vui lòng. " –