MATLAB:基于条件的不同尺寸的移动积分器(和)窗口

时间:2016-10-18 20:46:07

标签: arrays matlab indexing cumsum

我想根据array的值的累积和来定义移动积分器(和)窗口的起始和结束索引。每个窗口的累积和应小于或等于阈值。

此窗口的end_index对于将来的窗口统一向前移动1,但start_index取决于array的值。 start_index可以向前移动,保持相同或向后(负值),因此移动窗口的大小不固定。

例如:

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

对于start_index = 1,第一个窗口的array累积总和将为end_index = 5的5。

现在,对于下一个窗口,end_index向前移动1,以便新end_index = 6。我想知道如何通过反算新start_index的累计和来找到新的end_index,以便新cumsum小于或等于5窗户也是。在这种情况下,新的start_index = 4

有关如何完成的任何建议?

感谢。

2 个答案:

答案 0 :(得分:1)

我们的想法是,如果我们想从起始索引k获得累积和,则无需再次计算cumsum。相反,只有cumsum计算onec,而disired累积和是原始累积和与原始累积和的k-1元素之差

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)

注意:如果array的大小很大,以下实施可能会导致内存限制。相反,每次迭代都要对每个cmp和cmp1进行计算。

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)

答案 1 :(得分:0)

查找任何给定start_index的end_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 

查找任何给定end_index的start_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