How can I go through the matrix columns in matlab and add each one to a specific column of the sum matrix in matlab?

Suppose there is a Matrix

A =

 1     3     2    4
 4     2     5    8
 6     1     4    9

and I have a vector containing the "class" of each column of this matrix, for example

v = [1 , 1 , 2 , 3]

How can I sum the columns of a matrix with a new matrix as columns into columns of my class? In this example, columns 1 and 2 of A will be added to the first column of the new matrix, column 2 is the 3rd, column 4 is the third.

how

SUM =

4    2    4
6    5    8
7    4    9

Is this possible without cycles?

+4
source share
4 answers

One of the perfect scenarios for combining capacities accumarrayand bsxfun-

%// Since we are to accumulate columns, first step would be to transpose A
At = A.'  %//'

%// Create a vector of linear IDs for use with ACCUMARRAY later on
idx = bsxfun(@plus,v(:),[0:size(A,1)-1]*max(v))

%// Use ACCUMARRAY to accumulate rows from At, i.e. columns from A based on the IDs
out = reshape(accumarray(idx(:),At(:)),[],size(A,1)).'

Run Example -

A =
     1     3     2     4     6     0
     4     2     5     8     9     2
     6     1     4     9     8     9
v =
     1     1     2     3     3     2
out =
     4     2    10
     6     7    17
     7    13    17
+4

accumarray 2D. v, accumarray:

A = A.';

v = [1 1 2 3]; 

[X, Y] = ndgrid(v,1:size(A,2));

X Y :

X =

     1     1     1
     1     1     1
     2     2     2
     3     3     3


Y =

     1     2     3
     1     2     3
     1     2     3
     1     2     3

accumarray:

B=accumarray([X(:) Y(:)],A(:)),

SUM = B.'

SUM =

     4     2     4
     6     5     8
     7     4     9

, [X(:) Y(:)], :

ans =

     1     1
     1     1
     2     1
     3     1
     1     2
     1     2
     2     2
     3     2
     1     3
     1     3
     2     3
     3     3

v, "", 3 , 3 , .

EDIT:

knedlsepp, A B :

[X2, Y2] = ndgrid(1:size(A,1),v);

B = accumarray([X2(:) Y2(:)],A(:))

. , .

+3

?

result = full(sparse(repmat(v,size(A,1),1), repmat((1:size(A,1)).',1,size(A,2)), A));
+2

!

The loop is forgreat for your problem:

out = zeros(size(A,1), max(v));
for i = 1:numel(v)
    out(:,v(i)) = out(:,v(i)) + A(:,i);
end

By the way: with a good one, I mean: fast, fast, fast!

+1
source

All Articles