sum elements of matrix if...

Sargondjani (view profile)

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.

Azzi Abdelmalek

on 16 Oct 2012
Its not clear

Tags

Answer by Matt Tearle

Matt Tearle (view profile)

on 16 Oct 2012
Edited by Matt Tearle

Matt Tearle (view profile)

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

Matt Fig (view profile)

on 16 Oct 2012
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!

Sargondjani (view profile)

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!