How to find the closest value pair in a matrix?

45 visualizaciones (últimos 30 días)
Megha
Megha el 17 de Jul. de 2023
Comentada: Megha el 19 de Jul. de 2023
I have two numbers 0.85 and 1.25. I would like to find the closest pair of columns that contains both these values. I.e. A = [0.84 1.26; 0.90 1.24; 0.83 1.30]; and intersted pair is [0.85 1.25]. The closest pair from [0.85 1.25] is [0.84 1.26]. The difference is [-0.01 0.01], while for other pairs the difference is [0.04 -0.01] and [0.02 0.04]. So is there any way, I can make trial and error and find the closest pair of columns that has closest values? I tried following code, but it is not sufficient.
A = [0.84 1.26; 0.90 1.24; 0.83 1.30];
Pairs = [0.85 1.25];
for i = 1:size(Pairs,1)
loc = ismember(A,Pairs(i,:));
index(i,:)=find(sum(loc,2)==numel(Pairs(i,:)))';
end
Any help will be greatly appriciated. Thank you so much in advance!
  2 comentarios
Torsten
Torsten el 17 de Jul. de 2023
Is it given that A has only two columns and that the numbers in A and Pairs are in ascending order ?
Megha
Megha el 17 de Jul. de 2023
Yes, we can consider that A has only two columns but Pairs may not be in ascending order always..@Torsten

Iniciar sesión para comentar.

Respuesta aceptada

John D'Errico
John D'Errico el 17 de Jul. de 2023
Assuming that you have a much larger problem, and that you have multiple points, to test, knnsearch is the correct tool.
A = [0.84 1.26; 0.90 1.24; 0.83 1.30];
B = [0.85 1.25;.80 1.31];
IDX = knnsearch(A,B)
IDX = 2×1
1 3
So point number 1 in A is the closest to B(1,:), and point 3 in A is the closest to B(2,:).
Note that knnsearch will be much faster than exhaustively testing the points to see which is closest.
A = rand(1e6,2);
B = rand(1e5,2);
tic, IDX = knnsearch(A,B);toc
Elapsed time is 1.404760 seconds.
So only a little over a second to identify the nearest point in A for all of the 100000 points in B.

Más respuestas (3)

Voss
Voss el 17 de Jul. de 2023
A = [0.84 1.26; 0.90 1.24; 0.83 1.30];
Pairs = [0.85 1.25];
[~,idx] = min((Pairs(:,1).'-A(:,1)).^2 + (Pairs(:,2).'-A(:,2)).^2, [], 1);
closest = A(idx,:)
closest = 1×2
0.8400 1.2600
Note that the above method also works when you have multiple rows in Pairs:
% 3 points to find the closest point in A to:
Pairs = [0.85 1.25; 0.9 1.1; 0.95 1.4];
[~,idx] = min((Pairs(:,1).'-A(:,1)).^2 + (Pairs(:,2).'-A(:,2)).^2, [], 1);
closest = A(idx,:)
closest = 3×2
0.8400 1.2600 0.9000 1.2400 0.8300 1.3000
  1 comentario
Steven Lord
Steven Lord el 17 de Jul. de 2023
You can simplify and generalize the computation of the data you pass into your min call using vecnorm.
A = [0.84 1.26; 0.90 1.24; 0.83 1.30];
Pairs = [0.85 1.25];
distance1 = (Pairs(:,1).'-A(:,1)).^2 + (Pairs(:,2).'-A(:,2)).^2
distance1 = 3×1
0.0002 0.0026 0.0029
distance2 = vecnorm(Pairs-A, 2, 2).^2 % 2-norm squared along dimension 2
distance2 = 3×1
0.0002 0.0026 0.0029
This also lets you experiment with other norms.
distance3 = vecnorm(Pairs-A, 1, 2).^2 % 1-norm squared
distance3 = 3×1
0.0004 0.0036 0.0049
distance4 = vecnorm(Pairs-A, Inf, 2).^2 % Inf-norm squared
distance4 = 3×1
0.0001 0.0025 0.0025

Iniciar sesión para comentar.


Torsten
Torsten el 17 de Jul. de 2023
Movida: Torsten el 17 de Jul. de 2023
A = [0.84 1.26; 0.90 1.24; 0.83 1.30];
Pairs = [0.85 1.25];
Ah = sort(A, 2, 'ascend')
Ah = 3×2
0.8400 1.2600 0.9000 1.2400 0.8300 1.3000
Pairsh = sort(Pairs,'ascend')
Pairsh = 1×2
0.8500 1.2500
[~,idx] = min(sum(abs(Ah-Pairsh),2))
idx = 1
A(idx,:)
ans = 1×2
0.8400 1.2600

Bruno Luong
Bruno Luong el 17 de Jul. de 2023
For A that has at least 3 rows and the closest in the sense of l2 norm (auclidian distance), without the need of toolbox.
But if you have the toolbox @John D'Errico solution is faster.
A = [0.84 1.26; 0.90 1.24; 0.83 1.30]
A = 3×2
0.8400 1.2600 0.9000 1.2400 0.8300 1.3000
Pairs = [0.85 1.25]
Pairs = 1×2
0.8500 1.2500
T = delaunayTriangulation(A)
T =
delaunayTriangulation with properties: Points: [3×2 double] ConnectivityList: [2 3 1] Constraints: []
T.Points(T.nearestNeighbor(Pairs),:)
ans = 1×2
0.8400 1.2600
It can also handle a very large number of points
A = rand(1e6,2);
B = rand(1e5,2);
tic
T = delaunayTriangulation(A);
T.nearestNeighbor(B);
toc
Elapsed time is 4.397585 seconds.
  1 comentario
Megha
Megha el 19 de Jul. de 2023
Thank you @Torsten, @John D'Errico, @Voss, @Steven Lord for giving your valuable time. I agree that other methods works too but knnsearch was the quick and easy one for me to adapt! I appriciate your efforts.

Iniciar sesión para comentar.

Categorías

Más información sobre Linear Algebra en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by