Luke
Luke

Reputation: 53

MATLAB: summing values in matrix up to a threshold level of one column

So, I have a matrix with 2 columns and 5 rows (as an example).

2 1
5 1
3 1
4 1
7 1

what I want to do is:

Starting from position (1,1) and moving down the first column, find the cells that lead to a value <10. In this case I would have:

step 1: 2 = 10? No, continue
step 2: 2+5 = 10? No, continue
step 3: 2+5+3 = 10? Yes, stop and return the sum of the corresponding values in the second column
step 4: 4 = 10? No, continue
step 5: 4+7 = 10? No, it's larger, thus we save the previous step and return 1 form the second column.

In the end of this process I would need to obtain a new matrix that looks like this:

10 3
4 1
7 1

Upvotes: 0

Views: 61

Answers (2)

Tommaso Belluzzo
Tommaso Belluzzo

Reputation: 23685

This is my proposed solution:

% Create A and the cumulative sum of its first column...
A = [2 1; 5 1; 3 1; 4 1; 7 1];
A_cs = cumsum(A(:,1));

% Create a variable R to store the result and an indexer to it...
R = NaN(size(A_cs,1),2);
R_off = 1;

% Perform the computation...
while (~isempty(A_cs))
    idx = find(A_cs <= 10);
    idx_max = max(idx);

    R(R_off,:) = [A_cs(idx_max) sum(A(idx,2))];

    A_cs = A_cs - A_cs(idx_max);
    disp(A_cs);
    A_cs(idx) = [];

    R_off = R_off + 1;
end

% Clear unused slots in R...
R(any(isnan(R),2),:) = [];

The computation is performed by taking the maximum index of the first cumsum group that lies within the specified threshold (10 in this case). Once it has been found, its corresponding value is inserted into the result matrix and the cumsum array is updated by removing the group entries and subtracting their sum. When the cumsum array is empty, the iteration finishes and R contains the desired result.

Upvotes: 0

Wolfie
Wolfie

Reputation: 30165

You can perform exactly the logic you described in a loop.

  • Each row, test the "recent sum", where "recent" here means from the last output row to the current row.

  • If the sum is 10 or more, add to the output as described. Otherwise continue to the next row.

Code:

% Original data
x =[2 1; 5 1; 3 1; 4 1; 7 1];
% Output for result
output = [];
% idx is the row we start sum from on each test
idx = 1;
% Loop over all rows
for ii = 1:size(x,1)
    % Get sum in column 1
    s = sum(x(idx:ii, 1));
    if s == 10
        % Append row with sums
        output = [output; 10 sum(x(idx:ii,2))];
        idx = ii+1;
    elseif s > 10
        % Append all "recent" rows
        output = [output; x(idx:ii,:)];
        idx = ii+1;
    end
end

Result:

>> disp(output)
   10  3
    4  1
    7  1

Upvotes: 1

Related Questions