Asked by Sargondjani
on 16 Oct 2012

Hi,

lets say i have two matrices:

A=rand(5,10);

B=[ones(1,10);3*ones(1,10);ones(1,10);ones(1,10);3*ones(1,10)];

I know what to get a matrix C has 3 rows, and each row corresponds to the indexes in B. Each column in C should have the mean of the elements in A where the index in B == row number of C.

Now I do it like this, but i want to eliminate the step with D:

C=NaN(3,10);

for ii = 1:3;

D=NaN(size(A));

D(B==i)=A(B==i);

C(ii,:) = nanmean(D);

end

... the faster the better :-) thanks in advance!

The problem seems to be that A(B==ii) gives a column vector, while i want it to have the same size as A.

Answer by Matt Tearle
on 16 Oct 2012

Edited by Matt Tearle
on 16 Oct 2012

As far as I can figure out what you're doing, this is equivalent:

CRows = max(B(:));

C=NaN(CRows,10);

for i = 1:CRows;

C(i,:) = mean(A(all(B==i,2),:));

end

But it seems redundant to have a whole matrix of indices. Can you just do

C(i,:) = mean(A(B(:,1)==i,:));

or do you have to worry about the rows of B in some way?

EDIT TO ADD: BTW, if you have Statistics Toolbox, this will also work:

C = grpstats(A,B(:,1))

or

C = grpstats(A,nominal(B(:,1),[],1:CRows))

The latter keeps the row of NaNs (for indices that don't appear in B).

Matt Fig
on 16 Oct 2012

Sargondjani comments:

Ok, i was not clear let me try again. Actually, there is one more step, and I would like to do all without any for loop if possible...

VALUE = rand(6,10);

INDEX = round(3*rand(5,1)); %random indices between 0 and 3

INDEX(INDEX==0) = NaN;

For each column in VALUE i want the mean of the points with the same INDEX. This will be stored in a 3 by 10 matrix 'AVG_ind'. I can do this with a loop:

for ii = 1:3; TMP=NaN(size(VALUE)); for it = 1:10; VALUE(INDEX(:,it)==ii,it) TMP(INDEX(:,it)==ii,it)=VALUE(INDEX(:,it)==ii,it); end AVG_ind(ii,:) = nanmean(TMP,1); end

Is it possible to get rid of both loops? Or at least one?

Next I want to calculate the deviation of each point in VALUE compared the AVG_ind (with the corresponding index):

for ii = 1:3; for it = 1:10; DEV(INDEX(:,it)==ii,it) = VALUE(INDEX(:,it)==ii,it) / AVG_ind(ii,it); end end

And again, i hope this can also be done without any loops... Or at least I am pretty sure there is a fast way to calculate all the results much faster than what i do.

Again, many thanks for the help!

Sign in to comment.

Answer by Sargondjani
on 17 Oct 2012

It seems i can not edit my comment... so here again (sorry for mess, but i forgot to 'code' my code)

Ok, i was not clear let me try again. Actually, there is one more step, and I would like to do all without any for loop if possible...

VALUE = rand(6,10);

INDEX = round(3*rand(5,1)); %random indices between 0 and 3

INDEX(INDEX==0) = NaN;

For each column in VALUE i want the mean of the points with the same INDEX. This will be stored in a 3 by 10 matrix 'AVG_ind'. I can do this with a loop:

for ii = 1:3; TMP=NaN(size(VALUE)); for it = 1:10; VALUE(INDEX(:,it)==ii,it) TMP(INDEX(:,it)==ii,it)=VALUE(INDEX(:,it)==ii,it); end AVG_ind(ii,:) = nanmean(TMP,1); end

Is it possible to get rid of both loops? Or at least one?

Next I want to calculate the deviation of each point in VALUE compared the AVG_ind (with the corresponding index):

for ii = 1:3;

for it = 1:10;

DEV(INDEX(:,it)==ii,it) = ... VALUE(INDEX(:,it)==ii,it)/AVG_ind(ii,it);

end

end

And again, i hope this can also be done without any loops... Or at least I am pretty sure there is a fast way to calculate all the results much faster than what i do.

Again, many thanks for the help!

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Azzi Abdelmalek (view profile)

## Direct link to this comment

https://au.mathworks.com/matlabcentral/answers/50999-sum-elements-of-matrix-if#comment_105425

Sign in to comment.