A faster and more compact way to create a list of distances among all the pairs of points
2 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Sim
le 28 Avr 2023
Modifié(e) : chicken vector
le 29 Avr 2023
Hi, could you suggest a faster and more compact way to create a list of distances among all the pairs of points?
My attempt here below:
% Input (x and y coordinates of 6 points)
x = [1 2 2 3 4 5];
y = [1 2 3 7 2 5];
% Plot just to see the 6 points
plot(x,y,'o','MarkerFaceColor','b','markersize',15)
xlim([0 10])
ylim([0 10])
% Calculate the distances among each pair of points
Z = squareform(pdist([x' y']));
% Create a list that includes 3 elements: i-point ID, j-point ID, distance(i,j)
k = 1;
for i = 1 : length(x)-1
for j = i+1 : length(x)
list(k,:) = [i j Z(i,j)];
k = k + 1;
end
end
list,
0 commentaires
Réponse acceptée
chicken vector
le 29 Avr 2023
Modifié(e) : chicken vector
le 29 Avr 2023
N = 1e4;
x = randi(10,N,1);
y = randi(10,N,1);
tic
xIdx = repmat(1 : length(x), length(x), 1);
yIdx = xIdx';
vectorIdx = (1 : size(xIdx, 1))' > (1 : size(xIdx, 2));
xy = [x(:), y(:)];
dist = pdist2(xy, xy);
distPdist = dist(vectorIdx);
list = [xIdx(vectorIdx) , ...
yIdx(vectorIdx) , ...
distPdist]
toc
0 commentaires
Plus de réponses (2)
Image Analyst
le 28 Avr 2023
Try pdist2
% Input (x and y coordinates of 6 points)
x = [1 2 2 3 4 5];
y = [1 2 3 7 2 5];
xy = [x(:), y(:)]
% Get distances between every (x,y) point and every other (x,y) point:
distances = pdist2(xy, xy)
12 commentaires
Image Analyst
le 28 Avr 2023
No, I must be thinking of the old way. Anyway, you can post a "final" fixed up program for a new answer and he can accept that.
chicken vector
le 28 Avr 2023
Modifié(e) : chicken vector
le 28 Avr 2023
You can build the indeces without for loop:
N = 5e2;
x = randi(10,1,N);
y = randi(10,1,N);
% Loop method:
tic;
k = 1;
for i = 1 : length(x)-1
for j = i+1 : length(x)
loopList(k,:) = [i j];
k = k + 1;
end
end
loopTime = toc;
% Vectorised method:
tic;
xIdx = repmat(1 : length(x), length(x), 1);
yIdx = xIdx';
vectorList = [xIdx((1 : size(xIdx, 1))' > (1 : size(xIdx, 2))) , ...
yIdx((1 : size(yIdx, 1))' > (1 : size(yIdx', 2)))];
vectorTime = toc;
fprintf("Time with for loop: %.3f seconds\n", loopTime)
fprintf("Time with vectorisation: %.3f seconds\n", vectorTime)
You can also increase the speed for computing the distance with the following:
% Squareform method:
tic
squareFormZ = squareform(pdist([x' y']));
squareFormTime = toc;
% Vectorised method:
tic;
X = repmat(x, length(x), 1);
Y = repmat(y, length(y), 1);
deltaX = tril(x' - X, -1);
deltaY = tril(y' - Y, -1);
vectorZ = sqrt(deltaX(:).^2 + deltaY(:).^2);
vectorTime = toc;
fprintf("Time with squareform: %.3f seconds\n", squareFormTime)
fprintf("Time with vectorisation: %.3f seconds\n", vectorTime)
You can build your original list with the following wrapped up:
% Data:
x = [1 2 2 3 4 5];
y = [1 2 3 7 2 5];
% Initialise indeces:
xIdx = repmat(1 : length(x), length(x), 1);
yIdx = xIdx';
% Initialise elements distribution:
X = repmat(x, length(x), 1);
Y = repmat(y, length(y), 1);
% Compute distances:
deltaX = tril(x' - X, -1);
deltaY = tril(y' - Y, -1);
% Re-arrange to vector:
deltaX = deltaX((1 : size(deltaX, 1))' > (1 : size(deltaX, 2)));
deltaY = deltaY((1 : size(deltaY, 1))' > (1 : size(deltaY, 2)));
% Build lsit:
list = [xIdx((1 : size(xIdx, 1))' > (1 : size(xIdx, 2))) , ...
yIdx((1 : size(yIdx, 1))' > (1 : size(yIdx', 2))) , ...
sqrt(deltaX.^2 + deltaY.^2)]
0 commentaires
Voir également
Catégories
En savoir plus sur Get Started with Statistics and Machine Learning Toolbox dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!