Apply function to rolling window

前端 未结 5 759
自闭症患者
自闭症患者 2021-02-06 14:42

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))

5条回答
  •  耶瑟儿~
    2021-02-06 15:15

    Several functions can do the job efficiently in Matlab.

    On one side, you can use functions such as colfilt or nlfilter, which performs computations on sliding blocks. colfilt is way more efficient than nlfilter, but can be used only if the order of the elements inside a block does not matter. Here is how to use it on your data:

    S = colfilt(A, [100,1], 'sliding', @std);
    

    or

    S = nlfilter(A, [100,1], @std);
    

    On your example, you can clearly see the difference of performance. But there is a trick : both functions pad the input array so that the output vector has the same size as the input array. To get only the relevant part of the output vector, you need to skip the first floor((100-1)/2) = 49 first elements, and take 1000-100+1 values.

    S(50:end-50)
    

    But there is also another solution, close to colfilt, more efficient. colfilt calls col2im to reshape the input vector into a matrix on which it applies the given function on each distinct column. This transforms your input vector of size [1000,1] into a matrix of size [100,901]. But colfilt pads the input array with 0 or 1, and you don't need it. So you can run colfilt without the padding step, then apply std on each column and this is easy because std applied on a matrix returns a row vector of the stds of the columns. Finally, transpose it to get a column vector if you want. In brief and in one line:

    S = std(im2col(X,[100 1],'sliding')).';
    

    Remark: if you want to apply a more complex function, see the code of colfilt, line 144 and 147 (for v2013b).

提交回复
热议问题