2010-08-25 33 views
3

我有一個三列數據框:timestamp,key,按時間排序的事件。計算日誌中唯一值的總和R

ts,key,event 
3,12,1 
8,49,1 
12,42,1 
46,12,-1 
100,49,1 

由此,我想創建一個時間戳的數據幀(所有的唯一鍵 - 與累積和0,直到給定的時間戳所有的唯一密鑰)的所有獨特的按鍵劃分,直到相同的時間戳。例如。對於上述示例中的結果應該是:

ts,prob 
3,1 
8,1 
12,1 
46,2/3 
100,2/3 

我最初的一步是計算由關鍵分組的cumsum:

items = data.frame(ts=c(3,8,12,46,100), key=c(12,49,42,12,49), event=c(1,1,1,-1,1)) 
sumByKey = ddply(items, .(key), transform, sum=cumsum(event)) 

在第二(和最後)步驟i迭代sumByKey與用於並且使用向量跟蹤所有唯一鍵和所有唯一鍵的總和爲0,例如if(!(k %in% uniqueKeys) uniqueKeys = append(uniqueKeys, key)。概率是使用這兩個向量導出的。

最初,我嘗試使用plyr來解決第二步,但是我想避免重新計算sumByKey中每行的某個時間戳的唯一鍵。我缺少的是從傳遞給ddply的函數中引用外部變量的方法。或者,(或更多功能),使用傳遞迴該函數的累加器,例如函數(acc,x)acc + x。

是否有可能以更好的方式解決第二步, ddply?

+0

我不知道如果我理解正確的,但不應該成爲TS 46和100是2/3的結果(3唯一的鍵 - 1總和爲0)/ 3? – 2010-08-26 08:42:22

回答

2

如果我的理解是正確的,那麼這應該這樣做:

items = data.frame(ts=c(3,8,12,46,100), key=c(12,49,42,12,49), event=c(1,1,1,-1,1)) 

# numbers of keys that sum to zero, no ddply necessary 
nzero <- cumsum(ave(items$event,items$key,FUN=cumsum)==0) 

# number of unique keys at a given timepoint 
nunique <- rep(F,length(items$key)) 
nunique[match(unique(items$key),items$key)] <- T 
nunique <- cumsum(nunique) 

# makes : 
items$p <- (nunique-nzero)/nunique 

items 
    ts key event   p 
1 3 12  1 1.0000000 
2 8 49  1 1.0000000 
3 12 42  1 1.0000000 
4 46 12 -1 0.6666667 
5 100 49  1 0.6666667 
+0

我喜歡這個解決方案,非常高效和優雅,謝謝! – mkhq 2010-08-26 17:41:00

0

如果您的問題只是計算時間,我敢打賭更好的想法是將您的算法實現爲C塊;您可以首先使用R將密鑰轉換爲整數間隔(as.numeric(factor(...))),然後使用C中的布爾數組輕鬆快速地獲取唯一的密鑰號。請記住,plyr和標準R *pply都不比循環快得多(當然,提供兩者都沒有令人尷尬的錯誤)。

+0

我認爲這是我寫的,或者我只是不理解你的評論。 – mbq 2010-08-26 08:40:17