I have two equal sized vectors, e.g.
A=[2.29 2.56 2.77 2.90 2.05] and
B=[2.34 2.62 2.67 2.44 2.52].
I am interested to find closest values (almost equal) in two same size vectors A & B, i.e. out of all elements in A, which value is closest to any element of B? The solution should be extendable to any number of (equal size) vectors also. Means able to find closest values with a group of same sized vectors A,B &C. The two resulting values can be from either of two vectors.
For clarity, i am not interested to find closest values within a single vector. The answer from above example is values 2.56 and 2.52.
This works for a generic number of vectors of possibly different lengths:
vectors = {[2.29 2.56 2.77 2.90 2.05] [2.34 2.62 2.67 2.44 2.52] [1 2 3 4]};
% Cell array of data vectors; 3 in this example
s = cellfun(@numel, vectors); % Get vector lengths
v = [vectors{:}]; % Concatenate all vectors into a vector
D = abs(bsxfun(@minus, v, v.')); % Compute distances. This gives a matrix.
% Distances within the same vector will have to be discarded. This will be
% done by replacing those values with NaN, in blocks
bb = arrayfun(@(x) NaN(x), s, 'uniformoutput', false); % Cell array of blocks
B = blkdiag(bb{:}); % NaN mask with those blocks
[~, ind] = min(D(:) + B(:)); % Add that mask. Get arg min in linear index
[ii, jj] = ind2sub(size(D), ind); % Convert to row and column indices
result = v([ii jj]); % Index into concatenated vector
As a starting point for two vectors using bsxfun:
%// data
A = [2.29 2.56 2.77 2.90 2.05]
B = [2.34 2.62 2.67 2.44 2.52]
%// distance matrix
dist = abs(bsxfun(@minus,A(:),B(:).'));
%// find row and col indices of minimum
[~,idx] = min(dist(:))
[ii,jj] = ind2sub( [numel(A), numel(B)], idx)
%// output
a = A(ii)
b = B(jj)
now you can put it into a loop etc.
By the way:
dist = abs(bsxfun(@minus,A(:),B(:).'));
would be equivalent to the more obvious:
dist = pdist2( A(:), B(:) )
but I'd rather go for the first solution avoiding the overhead.
And finally the fully vectorized approach for multiple vectors:
%// data
data{1} = [2.29 2.56 2.77 2.90 2.05];
data{2} = [2.34 2.62 2.67 2.44 2.52];
data{3} = [2.34 2.62 2.67 2.44 2.52].*2;
data{4} = [2.34 2.62 2.67 2.44 2.52].*4;
%// length of each vector
N = 5;
%// create Filter for distance matrix
nans(1:numel(data)) = {NaN(N)};
mask = blkdiag(nans{:}) + 1;
%// create new input for bsxfun
X = [data{:}];
%// filtered distance matrix
dist = mask.*abs(bsxfun(@minus,X(:),X(:).'));
%// find row and col indices of minimum
[~,idx] = min(dist(:))
[ii,jj] = ind2sub( size(dist), idx)
%// output
a = X(ii)
b = X(jj)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With