MATLAB: Moving Integrator (Sum) Window with Varying Size, Based on a Condition

故事扮演 提交于 2019-12-02 03:07:56

问题


I'd like to define the start and end indices of a moving integrator (sum) window based on the cumulative sum of the values of array. Each window should have a cumulative sum of less than or equal to a threshold.

The end_index of this window is uniformly moving forward by 1 for the future windows, however the start_index is dependent on the values of array. start_index could move forward, stay the same or backwards (negative values), hence the size of this moving window is not fixed.

For example:

array = [ 1 0 2 1 1 2 0 0 1 2 0 1 0 1 1];

With the start_index = 1, the cumulative sum of array will be 5 at end_index = 5, for the first window.

Now for the next window, the end_index is moved forward by 1 such that the new end_index = 6. I'd like to know how I could find the new start_index by back calculating the cumulative sum from the new end_index so that cumsum is less than or equal to 5 for the new window as well. In this case, the new start_index = 4.

Any suggestions on how it could be done?

Thanks.


回答1:


The idea is that if we want to get cumulative sum from an starting index k there is no need again to compute cumsum. Instead only cumsum computed onec, and disired cumulative sum is difference of original cumulative sum and k-1th element of original cumulative sum

original_Summ = [1 1 3 4 5 7 7 7 8 10 10 11 11 12 13]
k=3
new_Summ = original_Summ - original_Summ(k-1)

Note: following implementation may cause memory limits if size of array is lage. Instead each cmp and cmp1 sould be compted in each iteration.

array = [ 1 0 2 1 1 2 0 0 1  2 0  1  0  1  1 ];
%forward cumsum
fwd = cumsum(array);
%backward cumsum
bkw = cumsum(array(end:-1:1));%cumsum(array,'reverse')
%difference of cumulative sum with all starting indices
cmp = bsxfun(@minus,fwd,[0 fwd(1:end-1)].');%in matlab r2016b cmp= fwd-[0 fwd(1:end-1)].'
cmp1= bsxfun(@minus,bkw,[0 bkw(1:end-1)].');%in matlab r2016b cmp1=bkw-[0 bkw(1:end-1)].'
%find last indices of elements  that are <=5
[r, c] = find(cmp <=5);
idx = accumarray(r,c,[],@max);
[r1, c1] = find(cmp1 <=5);
idx1 = accumarray(r1,c1,[],@max);
idx1 =flipud(numel(array) + 1-idx1);
%loop to find indices from previous indices
si = 1;
index={};
while true
    ei = idx(si);
    if ei == numel(array)
        break;
    end
    index {end+1} = [si,ei];
    ei = ei+1;
    si = idx1(ei);
    index {end+1} = [si,ei];
end
disp(index)



回答2:


To find the end_index for any given start_index:

start_index = 2;
threshold = 20;

if(sum(start_index:end)<threshold) %Error checking
    end_index = -1; 
else 
    end_index = find(cumsum(array(start_index:end)) >= threshold,1) + start_index - 1;
end 

To find the start_index for any given end_index:

end_index = 6;
threshold = 20;

if(sum(1:end_index)<threshold) %Error checking
    start_index = -1; 
else
    start_index = end_index + 1 - find(cumsum(fliplr(array(1:end_index))) >= threshold,1);

end %Error checking


来源:https://stackoverflow.com/questions/40117770/matlab-moving-integrator-sum-window-with-varying-size-based-on-a-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!