2
votes

I have a matrix A in Matlab. I would like your help to find an

  • algorithm summing the columns of A indexed by the same integer.

  • algorithm deleting the columns of A indexed by the same integer and putting instead one column of zero.

I thought about collapsing in one my two questions because I believe the solutions for the two algorithms should be similar once we've learnt how to pick the correct columns of A.

Let me explain better with an example.

clear 
b=8;
g=3;

B=[1;2;2;2;3;4;4;5]; %bx1
bnew=size(unique(B),1); 

A=[1  2  3  4  5  6  7  8;
   9  10 11 12 13 14 15 16;
   17 18 19 20 21 22 23 24]; %gxb

Regarding the first algorithm: the matrix B tells us which columns of A should be summed among each other. For example: the second, the third, and the fourth element of B are equal; this means that the second, the third, and the fourth columns of A should be summed.

Regarding the second algorithm: the matrix B tells us which columns of A should be deleted and replaced with a column of zeros. For example: the second, the third, and the fourth element of B are equal; this means that the second, the third, and the fourth columns of A should be deleted and one column of zeros should be added.

It is important to notice that the columns to sum up or to delete are always adjacent. In other words, we cannot have for example

B=[1;2;2;2;3;2;4;5];

These are the matrices I want to get and I couldn't find how.

Matrixdesired1=[1  2+3+4    5  6+7    8;
               9   10+11+12 13 14+15 16;
               17  18+19+20 21 22+23 24]; %gxbnew


Matrixdesired2=[1  0  5   0  8;
                9  0  13  0  16;
                17 0  21  0  24]; %gxbnew
3

3 Answers

3
votes

A solution using matrix multiplication:

C = B == 1:B(end);
Matrixdesired1 = A * C;

Matrixdesired2 = Matrixdesired1;
Matrixdesired2(:, sum(C) > 1) = 0;

or

Matrixdesired2 = Matrixdesired1 .* (sum(C) <= 1);

Here C is a [b * bnew] binary matrix. If it consumes large amount of memory you can create a sparse matrix and check for its efficiency:

C=sparse(1:numel(B),B,1);
1
votes

You can do this with a simple loop

b = b(:)'; % b should be a row vector
ub = unique(b);
out = zeros( size(A,1), numel(ub) );
for ii = 1:numel(ub)
    out(:,ii) = sum( A(:, b==ub(ii)), 2 );
end 

If you want to keep the column as zeros, just test if numel(b==ub(ii)) > 1 and don't do the sum in that case.

1
votes

For the first problem, you can use a one-liner with accumarray.

B=[1;2;2;2;3;4;4;5]; 

A=[1  2  3  4  5  6  7  8;
   9  10 11 12 13 14 15 16;
   17 18 19 20 21 22 23 24];

Matrixdesired1 = cell2mat(arrayfun(@(x) accumarray(B,A(x,:)),1:size(A,1),'un',0)).'

For the second problem, you may combine find and diff :

B=[1;2;2;2;3;4;4;5]; 

A=[1  2  3  4  5  6  7  8;
       9  10 11 12 13 14 15 16;
       17 18 19 20 21 22 23 24];

indx = find(diff(B.')==0);
A(:,indx+1)=zeros(size(A,1),numel(indx));
A(:,indx) = [];
Matrixdesired2 = A