如果你想要一个累积方差,你可以实现online-algorithm for variance。主要好处是它可以线性扩展,而不是像迭代所有可能的子集时那样呈指数增长。
如果你有
x<-c(3,1,7,5,1,3)
你可以的
cumvar<-function(x) {
tail(Reduce(local({mm<-0; nn<-0; function(a,b)
{nn<<-nn+1; d<-b-mm; mm<<-mm+d/nn; a+d*(b-mm)}}),
x, 0, accumulate=TRUE), -1)/(seq_along(x)-1)
}
cumvar(x)
# [1] NaN 24.500000 14.333333 10.000000 7.700000 6.166667 5.333333 4.696429 4.111111 3.777778
返回与
相同的结果
cumvar2 <- function(x) {
sapply(seq_along(x), function(i) var(x[1:i]))
}
cumvar2(x)
# [1] NA 24.500000 14.333333 10.000000 7.700000 6.166667 5.333333 4.696429 4.111111 3.777778
我们可以比较效率与
set.seed(15)
x<-rpois(100, 5)
microbenchmark:::microbenchmark(cumvar(x), cumvar2(x))
# Unit: microseconds
# expr min lq mean median uq max neval cld
# cumvar(x) 272.502 297.2425 335.2058 315.490 339.625 957.728 100 a
# cumvar2(x) 1672.323 1793.0960 2089.8104 1865.838 1956.208 6386.863 100 b
但是如果你想使用这个算法,如果你只计算方差一,我建议你阅读 wiki 页面,那么两遍方法更健壮。
您可以将它与dplyr 一起使用
dd<-read.table(text="team runs_scored date
LAN 3 2014-03-22
ARI 1 2014-03-22
LAN 7 2014-03-23
ARI 5 2014-03-23
LAN 1 2014-03-30
SDN 3 2014-03-30", header=T)
dd %>% mutate(cvar=lag(cumvar(runs_scored)))
# team runs_scored date cvar
# 1 LAN 3 2014-03-22 NA
# 2 ARI 1 2014-03-22 NaN
# 3 LAN 7 2014-03-23 2.000000
# 4 ARI 5 2014-03-23 9.333333
# 5 LAN 1 2014-03-30 6.666667
# 6 SDN 3 2014-03-30 6.800000