Суммируйте векторные значения до порога, затем начните снова

У меня есть вектор a = [1 3 4 2 1 5 6 3 2], Теперь я хочу создать новый вектор "б" с cumsum из a, но после достижения порога, скажем, 5, cumsum следует сбросить и запустить снова, пока он снова не достигнет порога, поэтому новый вектор должен выглядеть так:

b = [1 4 4 2 3 5 6 3 5]

Есть идеи?

4 ответа

Решение

Одним из способов является использование цикла. Вы создаете первую совокупную сумму cs, а затем, пока элементы в cs больше вашего порога thВы заменяете их элементами из совокупной суммы на остальные элементы в a,

Потому что некоторые элементы в a может быть больше, чем thэтот цикл будет бесконечным, если мы не исключим и эти элементы.

Вот простое решение с while цикл:

a = [1 3 4 2 1 5 6 3 2];
th = 5;
cs = cumsum(a);
while any(cs>th & cs~=a) % if 'cs' has values larger that 'th',
                       % and there are any values smaller than th left in 'a'
    % sum all the values in 'a' that are after 'cs' reached 'th',
    % excluding values that are larger then 'th'
    cs(cs>th & cs~=a) = cumsum(a(cs>th & cs~=a));
end

Вы можете построить разреженную матрицу, которая при умножении на исходный вектор возвращает кумулятивные суммы. Я не сравнивал это решение с другими, но сильно подозреваю, что оно будет самым быстрым для больших массивов.

% Original data
a = [1 3 4 2 1 5 6 3 2];
% Threshold
th = 5;
% Cumulative sum corrected by threshold
b = cumsum(a)/th;
% Group indices to be summed by checking for equality,
% rounded down, between each cumsum value and its next value. We add one to
% prevent NaNs from occuring in the next step. 
c = cumsum(floor(b) ~= floor([0,b(1:end-1)]))+1;
% Build the sparse matrix, remove all values that are in the upper
% triangle.
S = tril(sparse(c.'./c == 1));
% In case you use matlab 2016a or older:
% S = tril(sparse(bsxfun(@rdivide,c.',c) == 1));
% Matrix multiplication to create o.
o = S*a.';

Нормализуя аргументы cumsum с порогом и полом вы можете получить групповые показатели accumarray, который затем может сделать cumsum Минг по группам:

t = 5;
a = [1 3 4 2 1 5 6 3 2];

%// cumulative sum of normalized vector a 
n = cumsum(a/t);
%// subs for accumarray
subs = floor( n ) + 1;
%// cumsum of every group
aout = accumarray( subs(:), (1:numel(subs)).', [], @(x) {cumsum(a(x))});
%// gather results;
b = [aout{:}]

Рассчитайте накопленную сумму и замените значение индексов, следуя вашему состоянию.

 a = [1 3 4 2 1 5 6 3 2] ;

 b = [1 4 4 2 3 5 6 3 5] ;

 iwant = a ;
 a_sum = cumsum(a) ;
 iwant(a_sum<5) = a_sum(a_sum<5) ;
Другие вопросы по тегам