在滑动窗口内计算元素总和的最佳R语言是什么?滑动窗口的精度高于diff(cumsum(...))
概念欲以下:
for (i in 1:(length(input) - lag + 1))
output[i] <- sum(input[i:(i + lag - 1)])
换言之,每个输出元件应该是一个固定数量的输入元件(称为lag
这里)的总和,从而产生适当短结果向量。我知道我理论上可以这样写:
output = diff(cumsum(c(0, input)), lag = lag)
但我很担心这里的精度。我有一个设置记住所有的值都具有相同的符号,并且向量会很大。预先总结数值可能会导致数量偏大,因此个体差异不会留下许多有效数字。这感觉很糟糕。
我会想,应该可以做得比这更好,至少在使用单个函数而不是两个时。一个实现可以保持当前的总和,每个迭代添加一个元素并减去另一个元素。既然这样会一直累积舍入误差,我们可以从两端分别进行计算,如果中心的结果太远,则从中心计算一个新的结果,从而提高分水岭的精度,征服的方法。
你知道任何类似的东西吗?
或者有没有理由不这样做,因为我认为它应该?
或者为什么diff(cumsum(…))
的方法不像看起来那么糟糕?
编辑:我有一些关闭的情况的一个错误在我上面的配方,使他们不一致。现在他们似乎同意测试数据。 lag
应该是总结的元素的数量,因此我期望一个更短的向量。我不处理时间序列对象,所以绝对时间对齐与我无关。
我在我的真实数据中看到过一些看起来很嘈杂的东西,我认为这是由于这样的数字问题。由于使用不同的方法来计算这些值,使用不同的答案和评论的建议,仍然导致类似的结果,可能我的数据的奇怪实际上不是由于数字问题。
所以为了评价答案,我用下面的设置:
library(Rmpfr)
library(caTools)
len <- 1024*1024*8
lag <- 3
precBits <- 128
taillen <- 6
set.seed(42) # reproducible
input <- runif(len)
input <- input + runif(len, min=-1e-9, max=1e-9) # use >32 bits
options(digits = 22)
# Reference: sum everything separately using high precision.
output <- mpfr(rep(0, taillen), precBits = precBits)
for (i in 1:taillen)
output[i] <- sum(mpfr(input[(len-taillen+i-lag+1):(len-taillen+i)],
precBits=precBits))
output
addResult <- function(data, name) {
n <- c(rownames(resmat), name)
r <- rbind(resmat, as.numeric(tail(data, taillen)))
rownames(r) <- n
assign("resmat", r, parent.frame())
}
# reference solution, rounded to nearest double, assumed to be correct
resmat <- matrix(as.numeric(output), nrow=1)
rownames(resmat) <- "Reference"
# my original solution
addResult(diff(cumsum(c(0, input)), lag=lag), "diff+cumsum")
# filter as suggested by Matthew Plourde
addResult(filter(input, rep(1, lag), sides=1)[lag:length(input)], "filter")
# caTools as suggested by Joshua Ulrich
addResult(lag*runmean(input, lag, alg="exact", endrule="trim"), "caTools")
这样做的结果如下所示:
[,1] [,2]
Reference 2.380384891521345469556 2.036472557725210297264
diff+cumsum 2.380384892225265502930 2.036472558043897151947
filter 2.380384891521345469556 2.036472557725210741353
caTools 2.380384891521345469556 2.036472557725210741353
[,3] [,4]
Reference 1.999147923481302324689 1.998499369297661143463
diff+cumsum 1.999147923663258552551 1.998499369248747825623
filter 1.999147923481302324689 1.998499369297661143463
caTools 1.999147923481302324689 1.998499369297661143463
[,5] [,6]
Reference 2.363071143676507723796 1.939272651346203080180
diff+cumsum 2.363071143627166748047 1.939272651448845863342
filter 2.363071143676507723796 1.939272651346203080180
caTools 2.363071143676507723796 1.939272651346203080180
结果表明:diff
+ cumsum
仍然是令人惊讶的准确。 (在我想加入第二个runif
载体之前,它显得更加准确。)filter
和caTools
两者几乎都没有完美的结果。至于表现,我还没有测试(尚)。我只知道有128位的Rmpfr
cumsum
很慢,我不想等到它完成。如果您有性能基准或新的建议添加到比较中,请随时编辑此问题。
[caTools](http://cran.r-project.org/web/packages/caTools/)包有一些扩展的精度和。 –
Rmpfr或gmp是否有'cumsum'方法? –
@JoshuaUlrich:'caTools'看起来像一个有价值的参考资料,这是因为它的实现使得某些声明是正确的,并且因为它有一个相当大的“另请参见”列表,因此它是查找其他实现的好起点。你会做出答案吗? 'lag * runmean(input,lag,alg =“exact”,endrule =“trim”)'看起来与我所期望的相符。 'alg =“fast”似乎给了'diff' +'cumsum'更糟糕的结果。 – MvG