A faster and more compact way to create a list of distances among all the pairs of points
1 Ansicht (letzte 30 Tage)
Ältere Kommentare anzeigen
Sim
am 28 Apr. 2023
Bearbeitet: chicken vector
am 29 Apr. 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 Kommentare
Akzeptierte Antwort
chicken vector
am 29 Apr. 2023
Bearbeitet: chicken vector
am 29 Apr. 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 Kommentare
Weitere Antworten (2)
Image Analyst
am 28 Apr. 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 Kommentare
chicken vector
am 28 Apr. 2023
Bearbeitet: chicken vector
am 28 Apr. 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 Kommentare
Siehe auch
Kategorien
Mehr zu MATLAB Mobile finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!