将功能应用于滚动窗口 [英] Apply function to rolling window

查看:99
本文介绍了将功能应用于滚动窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个很长的值列表A(例如长度为1000),我要成对计算100个成对的std,即我想计算std(A(1:100))std(A(2:101)),...,std(A(901:1000)).

Say I have a long list A of values (say of length 1000) for which I want to compute the std in pairs of 100, i.e. I want to compute std(A(1:100)), std(A(2:101)), std(A(3:102)), ..., std(A(901:1000)).

在Excel/VBA中,您可以通过编写例如=STDEV(A1:A100)放入一个单元格,然后一口气填充.现在我的问题是,在不使用任何昂贵的for循环的情况下,如何在Matlab中高效地实现这一目标.


In Excel/VBA one can easily accomplish this by writing e.g. =STDEV(A1:A100) in one cell and then filling down in one go. Now my question is, how could one accomplish this efficiently in Matlab without having to use any expensive for-loops.


edit :是否还可以针对时间序列列表执行此操作,例如什么时候 A 的尺寸为1000 x 4(即长度为1000的4个时间序列)?然后,输出矩阵的尺寸应为901 x 4.

edit: Is it also possible to do this for a list of time series, e.g. when A has dimensions 1000 x 4 (i.e. 4 time series of length 1000)? The output matrix should then have dimensions 901 x 4.

推荐答案

注意:有关最快的解决方案,请参见 Luis Mendo的答案

Note: For the fastest solution see Luis Mendo's answer

因此首先为此使用一个for循环(尤其是如果这些是您的实际尺寸)确实不会很昂贵.除非您使用的是很旧的Matlab版本,否则JIT编译器(当然还有预分配)使for循环便宜.

So firstly using a for loop for this (especially if those are your actual dimensions) really isn't going to be expensive. Unless you're using a very old version of Matlab, the JIT compiler (together with pre-allocation of course) makes for loops inexpensive.

第二个-您是否尝试过循环?因为您真的应该先尝试天真的实现,然后再开始进行过早的优化.

Secondly - have you tried for loops yet? Because you should really try out the naive implementation first before you start optimizing prematurely.

第三-arrayfun可以使它成为一个衬套,但它基本上只是一个for循环,具有额外的开销,并且如果真正关心速度,则它可能比for循环慢.

Thirdly - arrayfun can make this a one liner but it is basically just a for loop with extra overhead and very likely to be slower than a for loop if speed really is your concern.

最后是一些代码:

n = 1000;
A = rand(n,1);
l = 100;

for循环(几乎不大,可能很有效):

for loop (hardly bulky, likely to be efficient):

S = zeros(n-l+1,1);  %//Pre-allocation of memory like this is essential for efficiency!
for t = 1:(n-l+1)
    S(t) = std(A(t:(t+l-1)));
end

向量化(内存效率低!)解决方案:

A vectorized (memory in-efficient!) solution:

[X,Y] = meshgrid(1:l)
S = std(A(X+Y-1))

可能是更好的矢量化解决方案(和单行代码),但内存效率仍然较低:

A probably better vectorized solution (and a one-liner) but still memory in-efficient:

S = std(A(bsxfun(@plus, 0:l-1, (1:l)')))

请注意,使用所有这些方法,您都可以将std替换为任何函数,只要将其自身应用于矩阵的列即可(这是Matlab中的标准)

Note that with all these methods you can replace std with any function so long as it is applies itself to the columns of the matrix (which is the standard in Matlab)

进行二维:

要进行2D操作,我们需要进行3D操作

To go 2D we need to go 3D

n = 1000;
k = 4;
A = rand(n,k);
l = 100;

ind = bsxfun(@plus, permute(o:n:(k-1)*n, [3,1,2]), bsxfun(@plus, 0:l-1, (1:l)'));    %'
S = squeeze(std(A(ind)));
M = squeeze(mean(A(ind)));
%// etc...

OR

[X,Y,Z] = meshgrid(1:l, 1:l, o:n:(k-1)*n);
ind = X+Y+Z-1;
S = squeeze(std(A(ind)))
M = squeeze(mean(A(ind)))
%// etc...

OR

ind = bsxfun(@plus, 0:l-1, (1:l)');                                                  %'
for t = 1:k
    S = std(A(ind));
    M = mean(A(ind));
    %// etc...
end

OR(取自 Luis Mendo的答案-请在他的答案中指出,他为该简单循环提供了一种更快的替代方法)

OR (taken from Luis Mendo's answer - note in his answer he shows a faster alternative to this simple loop)

S = zeros(n-l+1,k);
M = zeros(n-l+1,k);
for t = 1:(n-l+1)
    S(t,:) = std(A(k:(k+l-1),:));
    M(t,:) = mean(A(k:(k+l-1),:));
    %// etc...
end

这篇关于将功能应用于滚动窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆