我正在处理一组如下所示的数据:
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
我试图在此集上测试预测模型,其中一个输入参数是t-1中runs_scored
的方差。换句话说,为了预测第四次观察的结果变量,我需要根据数据集中先前的观察结果LAN
的方差。
我可以计算累积平均值和总和,但我无法弄清楚如何计算数据集中的累积方差。我在dplyr
中完成了大部分数据操作,但如果能够获得我需要的内容,我并不反对使用替代解决方案
答案 0 :(得分:11)
将方差公式写为(sum(x^2)-length(x)*mean(x)^2)/(length(x)-1)
,您可以看到它可以很容易地推广到累积差异,只需将其中的每个函数替换为累积版本(cummean
来自dplyr
})。所以,
library(dplyr)
cum_var <- function(x){
n <- 1:length(x)
(cumsum(x^2)-n*cummean(x)^2)/(n-1)
}
与@ MrFlick cumvar
的速度比较似乎令人鼓舞。
x <- rnorm(1e6)
all.equal(cum_var(x), cumvar(x))
#[1] TRUE
system.time(cumvar(x))[3]
elapsed
5.52
system.time(cum_var(x))[3]
elapsed
0.04
答案 1 :(得分:5)
如果您想要累积差异,则可以实施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
但是如果你想使用这个算法,我建议你阅读维基页面,如果你只计算方差一,那么双通法更健壮。
您可以将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
答案 2 :(得分:2)
你有一个大型数据集吗?如果for循环速度太慢,你可以这样做:
data$vars <- NA
for(i in 2:nrow(data)){
data$vars[i] <- var(data$runs_scored[1:(i - 1)])
}
这给出了
team runs_scored date vars
1 LAN 3 3/22/2014 NA
2 ARI 1 3/22/2014 NA
3 LAN 7 3/23/2014 2.000000
4 ARI 5 3/23/2014 9.333333
5 LAN 1 3/30/2014 6.666667
6 SDN 3 3/30/2014 6.800000
编辑:如果你想稍微加快一点,可以为这个应用程序编写一个特定的函数:
data$vars <- NA
cumVar <- function(position, df){
return(var(data$runs_scored[1:(position - 1)]))
}
然后使用sapply应用函数并获取向量:
position <- 3:nrow(data)
results <- c(NA,NA, sapply(position, cumVar,data))
data$var <- results
在我的机器上,大约30000行,for for循环,大约需要10.5秒,并且需要大约7.5秒。