2013-06-02 39 views
16

在我的工作中,我使用了幾個表格(客戶詳細信息,交易記錄等)。其中一些非常大(數百萬行),我最近切換到data.table包(感謝馬修)。然而,其中一些非常小(幾百行和4/5列)並且被稱爲幾次。因此,我開始考慮[.data.table開銷檢索數據,而不是設置()的價值,如已在?set中已清楚地描述的那樣,其中,無論表1的大小設置爲大約2微秒(取決於cpu)。從data.table和data.frame對象獲取單個元素的時間

但是,它似乎並不存在相當於setdata.table知道確切的行和列。一種loopable[.data.table

library(data.table) 
library(microbenchmark) 

m = matrix(1,nrow=100000,ncol=100) 
DF = as.data.frame(m) 
DT = as.data.table(m) # same data used in ?set 

> microbenchmark(DF[3450,1] , DT[3450, V1], times=1000) # much more overhead in DT 

Unit: microseconds 
expr  min  lq median  uq  max neval 
DF[3450, 1] 32.745 36.166 40.5645 43.497 193.533 1000 
DT[3450, V1] 788.791 803.453 813.2270 832.287 5826.982 1000 

> microbenchmark(DF$V1[3450], DT[3450, 1, with=F], times=1000) # using atomic vector and 
                   # removing part of DT overhead 
Unit: microseconds            
expr  min  lq median  uq  max neval 
DF$V1[3450] 2.933 3.910 5.865 6.354 36.166 1000 
DT[3450, 1, with = F] 297.629 303.494 305.938 309.359 1878.632 1000 

> microbenchmark(DF$V1[3450], DT$V1[3450], times=1000) # using only atomic vectors 
Unit: microseconds 
     expr min lq median uq max neval 
DF$V1[3450] 2.933 2.933 3.421 3.422 40.565 1000 # DF seems still a bit faster (23%) 
DT$V1[3450] 3.910 3.911 4.399 4.399 16.128 1000 

最後一種方法確實是最好的方法來快速檢索單個元素幾次。然而,set還要快

> microbenchmark(set(DT,1L,1L,5L), times=1000) 
Unit: microseconds 
       expr min lq median uq max neval 
set(DT, 1L, 1L, 5L) 1.955 1.956 2.444 2.444 24.926 1000 

問題是:如果我們能在set微秒2.444的值應該是不可能的得到在一個較小的(或至少相似的)量的值時間?謝謝。

編輯: 增加了兩個選項提示:

> microbenchmark(`[.data.frame`(DT,3450,1), DT[["V1"]][3450], times=1000) 
Unit: microseconds 
         expr min  lq median  uq  max neval 
`[.data.frame`(DT, 3450, 1) 46.428 47.895 48.383 48.872 2165.509 1000 
      DT[["V1"]][3450] 20.038 21.504 23.459 24.437 116.316 1000 

不幸並不比以前的嘗試更快。

+0

我同意你的問題,開銷可能/應該不是這麼多。儘管如此,DT'[[「V1」]] [3450]'? – Arun

+0

或者使用data.frame subsetting:''[.data.frame'(DT,3450,1)'('''應該是反引號的。) – Roland

+2

但是我對你覺得需要重複子集化有點懷疑。通常這意味着您可以通過更改算法進行優化。 – Roland

回答

7

感謝@hadley我們有解決方案!

> microbenchmark(DT$V1[3450], set(DT,1L,1L,5L), .subset2(DT, "V1")[3450], times=1000, unit="us") 
Unit: microseconds 
        expr min lq median uq max neval 
       DT$V1[3450] 2.566 3.208 3.208 3.528 27.582 1000 
     set(DT, 1L, 1L, 5L) 1.604 1.925 1.925 2.246 15.074 1000 
.subset2(DT, "V1")[3450] 0.000 0.321 0.322 0.642 8.339 1000