2013-08-20 13 views
2

行的限定數目和每個的位置(從-1000到+1000)並且對於每個位置的計數。一個小例子看起來這本:操作在我正在與具有數據組的數據表的一種工作data.table

dt.ex <- data.table(newID=rep(c("A","B"), each = 6), pos=rep(c(-2:3), 2), count= sample(c(1:100), 12)) 
    newID pos count 
1:  A -2 29 
2:  A -1 32 
3:  A 0 33 
4:  A 1 45 
5:  A 2 51 
6:  A 3 26 
7:  B -2 22 
8:  B -1 79 
9:  B 0  2 
10:  B 1 48 
11:  B 2 87 
12:  B 3 38 

我想要做的就是每n行之間計算平均值(或總和)爲每個組NEWID的。也就是說,分成n行並彙總結果。這將是輸出假設N = 3,總結:

newID pos count 
    A -2 94 
    A 1 122 
    B -2 103 
    B 1 173 

老實說,我對如何啓動,而不訴諸某種循環的不知道 - 不建議爲67094000×3臺。如果我只想計算每個newID,像this這樣的技巧就可以做到,但我還沒有看到一個解決方案接近回答我的問題。 Plyr解決方案也很受歡迎,儘管我覺得這可能太慢了。

+0

在您的輸出,你沒有的平均值'pos',而是最低/第一個值...? – Frank

+0

你的數據中有多少個獨特的'newID'? – Arun

回答

2

的另一種方法(不使用.SD)將是:

dt.ex[, seq := (seq_len(.N)-1) %/% 3, by=newID][, 
     list(pos = mean(pos), count=sum(count)), list(newID, seq)] 

標杆的(相對)更大的數據:

set.seed(45) 
get_grps <- function() paste(sample(letters, 5, TRUE), collapse="") 
grps <- unique(replicate(1e4, get_grps())) 

dt.in <- data.table(newID = sample(grps, 6e6, TRUE), 
       pos = sample(-1000:1000, 6e6, TRUE), 
       count = runif(6e6)) 
setkey(dt.in, newID) 

require(microbenchmark) 
eddi <- function(dt) { 
    dt[, .SD[, list(pos = mean(pos), count = sum(count)), 
      by = seq(0, .N-1) %/% 3], by = newID] 
} 

arun <- function(dt) { 
    dt[, seq := (seq_len(.N)-1) %/% 3, by=newID][, 
     list(pos = mean(pos), count=sum(count)), list(newID, seq)] 
} 

microbenchmark(o1 <- eddi(copy(dt.in)), o2 <- arun(copy(dt.in)), times=2) 


Unit: seconds 
        expr  min  lq median  uq  max neval 
o1 <- eddi(copy(dt.in)) 25.23282 25.23282 26.16009 27.08736 27.08736  2 
o2 <- arun(copy(dt.in)) 13.59597 13.59597 14.41190 15.22783 15.22783  2 
1

試試這個:

dt.ex[, .SD[, list(pos = mean(pos), count = sum(count)), 
       by = seq(0, .N-1) %/% 3], 
     by = newID] 

注意父data.table.N嵌套by使用,因爲.N只有在j-expression存在。

+2

隨着唯一'newID'數量的增加和'n'數量的減少(導致分組太多),使用'.SD'會變得更慢。 'DT [,SEQ:=(seq_len(.N)-1)%/%3,= NEWID] [,列表(POS =平均值(POS),計數=總和(計數)),列表(NEWID,SEQ) ]'會比較快。在600萬行上,'.SD'需要26秒,而另一個需要12秒。 – Arun

+0

@阿倫在我的測試中不是這樣,但你應該自己測試;嗯,我想你做了 - 對我來說這很奇怪,這是另一種方式,我會張貼一張長凳 – eddi

+0

好吧,讓我發佈我的基準,以便您可以驗證。 – Arun