我有一个包含三列的数据框:timestamp,key,按时间排序的事件。
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))
在第二个(也是最后一个)步骤中,我使用for循环迭代sumByKey
并跟踪所有唯一密钥和所有使用向量在其总和中为0的唯一密钥,例如if(!(k %in% uniqueKeys) uniqueKeys = append(uniqueKeys, key)
。使用两个向量导出概率。
最初,我尝试使用plyr解决第二步,但我想避免为sumByKey
中的每一行重新计算特定时间戳的唯一键。我遗漏的是一种从传递给ddply的函数引用外部变量的方法。或者,或者(并且更具功能性),使用传递回函数的累加器,例如, function(acc,x)acc + x。
是否有可能以更好的方式解决第二步,例如, ddply?
答案 0 :(得分: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
答案 1 :(得分:0)
如果您的问题只是计算时间,我敢打赌更好的想法是将您的算法实现为C块;您可以先使用R将密钥转换为整数的相干间隔(as.numeric(factor(...))
),然后在C中使用布尔数组,以便轻松快速地获取唯一的密钥编号。请记住,plyr和标准R *pply
都不比循环快得多(当然,两者都使用而没有令人尴尬的错误)。