这是一个有趣的问题,因为我认为对于平均值来说最优解与其他样本统计量不同。下面提供了一个模拟示例供您参考。
首先,选择一些任意参数并模拟一些数据:
T = 100; N = 5;
WindowLength = 10;
X = randn(T, N);
对于均值,使用filter
来获取移动平均值:
MeanMA = filter(ones(1, WindowLength) / WindowLength, 1, X);
MeanMA(1:WindowLength-1, :) = nan;
我最初想使用 conv
来解决这个问题,如下所示:
MeanMA = nan(T, N);
for n = 1:N
MeanMA(WindowLength:T, n) = conv(X(:, n), ones(WindowLength, 1), 'valid');
end
MeanMA = (1/WindowLength) * MeanMA;
但是,正如@PhilGoddard在评论中指出的那样,filter
方法避免了使用循环的必要。
另外请注意,我选择使输出矩阵中的日期与X
中的日期对应,因此,在后续工作中您可以为两者使用相同的下标。 因此,MeanMA
中前WindowLength-1
个观测值将为nan
。
至于方差,我无法想到如何使用filter
或conv
甚至是一个运行总和来实现更高效的计算,因此我在每次迭代时手动执行计算:
VarianceMA = nan(T, N);
for t = WindowLength:T
VarianceMA(t, :) = var(X(t-WindowLength+1:t, :));
end
我们可以利用已经计算出来的平均移动平均值,稍微加快速度。只需将上述代码中的循环内部行替换为:
VarianceMA(t, :) = (1/(WindowLength-1)) * sum((bsxfun(@minus, X(t-WindowLength+1:t, :), MeanMA(t, :))).^2);
不过,我怀疑这样做并不会有太大的区别。
如果有人能想到一个巧妙地使用 filter
或者 conv
来获得移动窗口方差的方法,我将非常感兴趣。
至于偏度和峰度的情况,我将其留给OP,因为它们与方差示例本质上是相同的,只需适当的函数即可。
最后要说的一点是:如果您将上述内容转换为通用函数,可以将匿名函数作为参数之一传入,那么您将拥有一个适用于任意变换选择的移动平均计算程序。
最后一个观点:对于一系列的窗口长度,只需为每个窗口长度循环整个代码块即可。
filter
函数,这样可以消除循环的需要。对于其他统计数据,只能使用循环。 - Phil Goddardfilter
函数在我的视线范围之外。我已经更新了我的答案,包括这种方法。 - Colin T Bowersfilter
函数。对于Matlab的一个通用规则(尽管这些天由于JIT编译器的进步而不那么重要)是通过向量化代码来避免循环。这就是我答案中filter
函数的目的。 - Colin T Bowers