Суммируйте векторные значения до порога, затем начните снова
У меня есть вектор 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) ;