How to create for loop for calculating euclidean distance of a matrix?
9 views (last 30 days)
Show older comments
Hi!
I am having some trouble figuring out how to structure this for loop.. I have an array called 'Coordinates' that contains a varying number of rows, and constant number of columns. col 1 = x, col 2 = y, col 3 = z. The number of rows varies based on how many events occur in a single observation, but columns are consistent throughout.
Coordinates =
-.6 .5 -4.1
-.9 .4 -4.1
-1.1 .2 -4.2
I need to write a for loop that calculates the euclidean distance between each of these xyz coordinates and store it in a new array called 'Distances'.
icoordinates = nobservations - 1; %creates a variable that consists of number of observations -1
config.Calculated.Distances = []; % create empty vector to store distances
for i_coord = 1:icoordinates %for each observation
curdistance = config.Calculated.Coordinates(:, :, i_coord);
curdistance = sqrt(sum((Coordinates(i+1,:) - Coordinates(i,:)).^2));
config.Calculated.Distances = [config.Calculated.Distances curdistance];
end
close all;
When I run the code as above ^ I get the following error and my Distances array remains empty
1 icoordinates = nobservations - 1; % creates a variable that consists of number of scan patterns -1
Index in position 1 is invalid. Array indices must be positive integers or logical values.
Error in distancecalc (line 7)
curdistance = sqrt(sum((Coordinates(i+1,:) - Coordinates(i,:)).^2));
Any help with figuring out how to structure this for loop would be greatly appreciated, I'm a MATLAB novice and would love to learn!
Thanks,
Jade
0 Comments
Accepted Answer
Voss
on 3 Apr 2024
Something like what follows might be what you're trying to do (I'm assuming config.Calculated.Coordinates is the same as Coordinates). This calculates the distance between each consecutive pair of points (i.e., each pair of adjacent rows in the Coordinates matrix):
Coordinates = [
-0.6 0.5 -4.1
-0.9 0.4 -4.1
-1.1 0.2 -4.2
];
nobservations = size(Coordinates,1);
icoordinates = nobservations - 1; %creates a variable that consists of number of observations -1
Distances = []; % create empty vector to store distances
for i_coord = 1:icoordinates %for each observation
curdistance = sqrt(sum((Coordinates(i_coord+1,:) - Coordinates(i_coord,:)).^2));
Distances = [Distances curdistance];
end
Distances
However, rather than growing your Distances vector one element at a time, it is a good idea to pre-allocate it (especially if the number of observations is large), since appending one element at a time to a vector is inefficient. To Pre-allocate an array is to initialize it to the correct size with zeros (or whatever value makes sense in context) before calculating its elements' values in a loop.
Distances = zeros(1,icoordinates); % pre-allocated row vector of Distances
for i_coord = 1:icoordinates %for each observation
curdistance = sqrt(sum((Coordinates(i_coord+1,:) - Coordinates(i_coord,:)).^2));
Distances(i_coord) = curdistance; % assign the i_coord element of Distances
end
Distances
Now, as with many things in MATLAB, there are useful functions for doing this without a loop. In this case you can use the diff function to take the differences between adjacent rows of Coordinates, which produces an icoordinates-by-3 matrix, and also specify in the sum function that the sum is to be done over the second dimension - that is, to sum the columns of the squared differences (since now all rows are being operated on at once).
Distances = sqrt(sum(diff(Coordinates, 1, 1).^2, 2));
% ^ first difference
% ^ over the first dimension (row-by-row)
% ^ sum across the second dimension (sum the columns)
Distances
Of course, it could be that you don't mean to be finding the distances only between the coordinates in adjacent rows of Coordinates but between each row and every other row. To do that using your intial approach requires two nested for loops. The second loop starts at i_coord+1 so that you're not calculating the distance between a point and itself and not repeating any pairs (i.e, the distance between point A and point B is the same as the distance between point B and point A - no need to calculate that distance twice):
Distances = []; % create empty vector to store distances
for i_coord = 1:nobservations %for each observation
for j_coord = i_coord+1:nobservations % and each subsequent observation
curdistance = sqrt(sum((Coordinates(j_coord,:) - Coordinates(i_coord,:)).^2));
Distances = [Distances curdistance];
end
end
Distances
(Notice there's an extra element in Distances now, the distance between point 1 (first row) and point 3 (third row), which was not calculated before.)
That can be done without any loops as well (this calculates every pairwise distance, including A->B and B->A (note the symmetry of the result) and the distance from a point to itself (note the zeros along the diagonal)):
Distances = sqrt(sum((permute(Coordinates,[1 3 2]) - permute(Coordinates,[3 1 2])).^2, 3))
More Answers (1)
See Also
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!