Find closest value in array
Show older comments
I have two vector(which are time stamps) like, V N 1375471092848936 1375473384440853 1375473388165900 1375471277856598 1375471320476780 1375473388165900 1375473388947681 1375471322465961 1375473392527002 1375471335206288 .................. .................. My goal is to find closest time in N with respect to V (i.e. find time in N which is nearly equal with V). My frame is W = 1e4, furthermore V should lies between N-W and N+W. So how do I get closest time through MATLAB? Any help would be appreciated. Thanks
Accepted Answer
More Answers (5)
Andrew Reibold
on 25 Aug 2014
Edited: Andrew Reibold
on 25 Aug 2014
This finds the value in N which is closest to the V value I am calling.
N = [1990 1998 2001 2004 2001]
V = [2000 2011 2010 2001 1998]
[c index] = min(abs(N-V(1)))
In this case Im looking for the closest value to 'V(1)' which is 2000. It should return the 3rd or 5th value of N which is 2001.
Note: 'index' is the index of the closest value. If two are the same, like in this example with two different '2001's, it will return the index of the first one.
4 Comments
Gijs de Vries
on 6 Oct 2017
So simple but yet so effective and elegant! I am a bit ashamed that I did not figure this out by my self.
Image Analyst
on 6 Oct 2017
Caution/Note: This solution only compares a row to the very same row in the other vector. My solution compares all rows to all other rows. So this solution might come up with, say, row 40 as the closest distance, but my solution might come up with a closer distance between row 34 or N with row 53 of V.
If you have the Statistics and Machine Learning Toolbox, you can also compute the distance between every element and every element of the other array using the function pdist2().
So it really depends if you want the closest distance between corresponding rows (this solution), or if you want the overall closest distance no matter what rows they may occur in (my solution).
reetu hooda
on 17 Feb 2018
if N is just a decimal number and it is to be searched in a matrix V(containing decimal numbers). how would the code change?
Image Analyst
on 17 Feb 2018
reetu, if N is just a single number then you can do this
[minDistance, indexOfMin] = min(abs(V-N));
Image Analyst
on 25 Aug 2014
How about this:
clc;
% Sample data
numberOfRows = 5;
V = rand(numberOfRows, 1)
N = rand(numberOfRows, 1)
% Find min distance
minDistance = inf;
for ni = 1 : numberOfRows
for vi = 1 : numberOfRows
distances(vi, ni) = abs(N(ni) - V(vi));
if distances(vi, ni) < minDistance
minNRow = ni;
minVRow = vi;
minDistance = distances(vi, ni);
end
end
end
% Report to command window:
distances
fprintf('Closest distance is %f which occurs between row %d of N and row %d of V\n',...
minDistance, minNRow, minVRow);
In the command window:
V =
0.5309
0.6544
0.4076
0.8200
0.7184
N =
0.9686
0.5313
0.3251
0.1056
0.6110
distances =
0.4378 0.0005 0.2057 0.4252 0.0801
0.3142 0.1231 0.3293 0.5488 0.0435
0.5610 0.1237 0.0825 0.3020 0.2033
0.1487 0.2886 0.4948 0.7144 0.2090
0.2503 0.1870 0.3932 0.6127 0.1074
Closest distance is 0.000470 which occurs between row 2 of N and row 1 of V
3 Comments
Aristo
on 2 Nov 2017
@Image Analyst- is there a shortcut method to it or getting read of for loop and including all values between 0 and 0.2
Image Analyst
on 2 Nov 2017
You can try this:
% Sample data
numberOfRows = 5;
V = rand(numberOfRows, 1)
N = rand(numberOfRows, 1)
% Find min distance
distances = pdist2(V, N)
[minDistance, index] = min(distances(:))
[minVRow, minNRow] = ind2sub(size(distances), index)
fprintf('The closest distance is %f which occurs between\nrow %d of V (%f) and\nrow %d of N (%f)\n',...
minDistance, minVRow, V(minVRow), minNRow, N(minNRow));
% Double-check / Prove it
V(minVRow) - N(minNRow)
Image Analyst
on 10 Nov 2017
What's wrong with a for loop? And what is ni and vi?
John D'Errico
on 10 Jul 2024
Edited: John D'Errico
on 10 Jul 2024
To be honest, the easiest way is to use knnsearch. It works well in one dimension, as you have here, and it should be quite efficient.
V = [1375471092848936; 1375473388165900; 1375471320476780; 1375473388947681; 1375473392527002];
N = [1375473384440853; 1375471277856598; 1375473388165900; 1375471322465961; 1375471335206288];
help knnsearch
ids = knnsearch(N,V)
There is no need to look at differences, compute absolute values, etc. Just use the tool that is designed to solve your problem directly.
As of release R2021b, you don't need to use abs on the input to the min function. Use the 'ComparisonMethod' option to tell MATLAB to take the minimum value by absolute value.
V = randi(100,[5 1])
N = randi(100,[5 1])
[minDifference,closestIndex] = min(N-V.', [], ComparisonMethod = "abs")
closestValue = N(closestIndex)
4 Comments
Steven Lord
on 4 Feb 2025
And if you're trying to perform matching, where you're trying to match elements of V with elements of N on a one-to-one basis (no two elements of V can match with the same element of N and vice versa) consider the matchpairs function.
From the sounds of it I was hoping matchpairs would find a matching pair in an array of pairs. That would be convenient since ismember is so tricky that I have to consult the documentation every time I use it. But I guess matchpairs doesn't do that or else I'm not using it correctly.
% Define variables to search and search for.
allValues = [1,20; 2,30; 3, 40; 4, 50; 5, 60]
sought = [3, 40];
% ismember() works, though it's always tricky to figure out.
[a, b] = ismember(sought, allValues) % Find the row where it occurs
rowFound = allValues(b(1), :) % Extract the row to make sure it matches sought
% Matchpairs() doesn't work like this (like I'd hope for)
rowFound = matchpairs(sought, allValues, 'min')
For the case you described you probably want to use the 'rows' option for ismember. [This assumes the row you're searching for is in the matrix you're searching, not 'close to' a row in the matrix. In that case you'd want to use ismembertol with ByRows=true.]
% Define variables to search and search for.
allValues = [1,20; 2,30; 3, 40; 4, 50; 5, 60]
sought = [3, 40];
[~, whichRow] = ismember(sought, allValues, 'rows')
matchpairs is intended to solve a different problem. It solves the combinatorial optimization assignment problem. It is intended to associate the elements of two different sets along with a cost or value for each association to minimize cost or maximize value, matching pairs of elements from those sets. One example is if you have workers and tasks, and each worker is more or less skilled with different tasks or is more or less satisfied with those tasks. You may want to assign each task to a worker maximizing the overall skill or the job satisfaction of the group of workers with their assignments.
Image Analyst
on 8 Feb 2025
Thanks Steve. I forgot about the 'rows' option. 🙂
Korosh Agha Mohammad Ghasemi
on 25 Jun 2024
Moved: Voss
on 25 Jun 2024
% Example V and N vectors
V = [1375471092848936; 1375473388165900; 1375471320476780; 1375473388947681; 1375473392527002];
N = [1375473384440853; 1375471277856598; 1375473388165900; 1375471322465961; 1375471335206288];
W = 1e4; % Window size
% Initialize the closest times array
closest_times = zeros(size(V));
% Find the closest time in N for each time in V within the window
for i = 1:length(V)
% Calculate the absolute differences
diffs = abs(N - V(i));
% Find the indices within the window
within_window = diffs <= W;
if any(within_window)
% Find the closest time
[~, closest_idx] = min(diffs(within_window));
% Get the actual index in N
closest_times(i) = N(find(within_window, closest_idx, 'first'));
else
% No times within the window
closest_times(i) = NaN;
end
end
% Display the closest times
disp('Closest times:');
disp(closest_times);
Categories
Find more on Matrix Indexing 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!