From: Raphael on
Hello,

This is what I am trying to do : I have an n*3 matrix of cell velocities in space 'Velocity' and an n*n logical matrix of neighbourhood relationships 'Neigh' (0 if stranger, 1 if neighbour). n is about 5000 to 10000. Some speeds are NaN.

To average speed in space, I did the following :

AverageVelocity=NaN(n, 3);
for i=1:n
AverageVelocity(i,:)=nanmean(Velocity(Neigh(:,i),:));
end

Is there a way to overcome the for loop ? I am interested in speeding up computation and, in general, in learning new strategies for "elegant" coding in matlab.

Thank you,
Raphaël
From: Yi Cao on
"Raphael " <raphael.keller(a)gmail.com> wrote in message <hq99e6$736$1(a)fred.mathworks.com>...
> Hello,
>
> This is what I am trying to do : I have an n*3 matrix of cell velocities in space 'Velocity' and an n*n logical matrix of neighbourhood relationships 'Neigh' (0 if stranger, 1 if neighbour). n is about 5000 to 10000. Some speeds are NaN.
>
> To average speed in space, I did the following :
>
> AverageVelocity=NaN(n, 3);
> for i=1:n
> AverageVelocity(i,:)=nanmean(Velocity(Neigh(:,i),:));
> end
>
> Is there a way to overcome the for loop ? I am interested in speeding up computation and, in general, in learning new strategies for "elegant" coding in matlab.
>
> Thank you,
> Raphaël


Hi Raphael,

You can try the following code

% some example data
n=10;
Velocity=randn(n,3);
Neigh=rand(n)>0.6;

% the actual calculation
AverageVelocity = daig(1./sum(Neigh))*Neigh*Velocity;
From: Raphael on
> Hi Raphael,
>
> You can try the following code
>
> % some example data
> n=10;
> Velocity=randn(n,3);
> Neigh=rand(n)>0.6;
>
> % the actual calculation
> AverageVelocity = daig(1./sum(Neigh))*Neigh*Velocity;

Hello Yi Cao,

Thank you very much. Your solution is very easy and algebric, but the creation of the diagonal matrix takes a "lot" of time (compared to the simple for loop, maybe because matlab is transforming Neigh from sparse to full ?). To get the first part diag(1./sum(Neigh))*Neigh, I tried :

bsxfun(@times, Neigh, 1./sum(Neigh));

but matlab says "operands must be full", so the problem is the same.
From: vortse a on
Yi Cao has made a typo, he means to use the "diag" command. However there are two issues:

1. The results do not check. I don't know why.

2. This solution takes much more time. For n=10000:
t1 =
164.4041
t2 =
3.1899
I believe it is the diag command which delays the calculation, because it creates a new n*n matrix.

Here is my comparison code:

% some example data
n=1000;
Velocity=randn(n,3);
Neigh=rand(n)>0.6;
tic
% the actual calculation
AverageVelocity1 = diag(1./sum(Neigh))*Neigh*Velocity;
t1=toc
tic
% old code
AverageVelocity2=NaN(n, 3);
for i=1:n
AverageVelocity2(i,:)=nanmean(Velocity(Neigh(:,i),:));
end
t2=toc
% check results
resultcheck=all(lt(abs(AverageVelocity1-AverageVelocity2),10^-8))
From: Raphael on
"vortse a" <sonoffeanor-remove(a)yahoo.com> wrote in message <hq9lve$2gh$1(a)fred.mathworks.com>...
> Yi Cao has made a typo, he means to use the "diag" command. However there are two issues:
>
> 1. The results do not check. I don't know why.
>

I think this is because the random matrix is not symmetric, while the neighbourhood matrix is. Yi Cao's calculation works on the rows (in the matrix multiplication), mine on columns.