Arrays 如何在一个向量中找到与另一个向量最近的值?

Arrays 如何在一个向量中找到与另一个向量最近的值?,arrays,matlab,vector,distance,Arrays,Matlab,Vector,Distance,我有两个大小相等的向量,例如 A=[2.29 2.56 2.77 2.90 2.05] and B=[2.34 2.62 2.67 2.44 2.52]. 我感兴趣的是在两个相同大小的向量A和B中找到最接近的值(几乎相等),即在A中的所有元素中,哪个值最接近B中的任何元素?该解决方案还应可扩展到任意数量(大小相等)的向量。指能够通过一组大小相同的向量a、B和C找到最接近的值。两个结果值可以来自两个向量中的任何一个 为了清楚起见,我不想在单个向量中找到最接近的值。上述示例的答案是值2.56和2.

我有两个大小相等的向量,例如

A=[2.29 2.56 2.77 2.90 2.05] and
B=[2.34 2.62 2.67 2.44 2.52].
我感兴趣的是在两个相同大小的向量A和B中找到最接近的值(几乎相等),即在A中的所有元素中,哪个值最接近B中的任何元素?该解决方案还应可扩展到任意数量(大小相等)的向量。指能够通过一组大小相同的向量a、B和C找到最接近的值。两个结果值可以来自两个向量中的任何一个


为了清楚起见,我不想在单个向量中找到最接近的值。上述示例的答案是值2.56和2.52。

作为两个向量的起点,使用:

现在你可以把它放进一个循环,等等


顺便说一下:

dist = abs(bsxfun(@minus,A(:),B(:).'));
相当于更明显的:

dist = pdist2( A(:), B(:) )
但我宁愿选择第一种解决方案,避免开销


最后是针对多个向量的完全矢量化方法:

%// 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)

这适用于长度可能不同的向量的通用编号

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

正如一篇长篇评论一样,如果您可以访问统计和机器学习工具箱,那么您可以使用K-最近邻函数,该函数具有以下优点:

  • 处理不同长度的数组,例如当大小(A)=[M,1]和大小(B)=[N,1]

  • 处理二维数组,例如当大小(A)=[M,d]和大小(B)=[N,d]

  • 处理不同的距离类型,例如:欧几里德距离、城市街区距离、切比雪夫距离和其他许多距离类型,甚至您拥有自定义距离

  • 在一些特殊情况下使用KDTree算法,可以获得很好的性能

  • 虽然在您的例子中,“Luis Mendo”的答案看起来很好,但它并不像工具箱中的K近邻函数那样可扩展

    更新:示例代码

    % A and B could have any Dimension, just same number of columns (signal Dimension)
    A = rand(1000,4);
    B = rand(500,4);
    
    % Use any distance you like, some of them are not supported for KDTreeSearcher,
    % and you should use ExhaustiveSearcher
    myKnnModel= KDTreeSearcher(A, 'Distance', 'minkowski');
    
    % you can ask for many (K) Nearest Neighbors and you always have access to it for later uses
    [Idx, D] = knnsearch(myKnnModel, B, 'K',2);
    
    % and this is answer to your special case
    [~, idxA] = min(D(:, 1))
    idxB = Idx(idxA)
    

    对于两个向量,代码运行良好。如何将其扩展为三个或更多向量?@erbal所有向量的长度都相同吗?@erbal这是一个相对较新的函数,看看这里的SO,你会发现replacement@erbal我用
    blkdiag
    (灵感来自Luis Mendo)改进了我的解决方案,您不再需要重复,也不需要太多内存;)正在尝试更新的代码,因为在任何地方都找不到Replem。哇,很好的解决方案!我借用了你的
    blkdiag
    idea;)+代码工作正常。还可以处理不同的向量长度。@thewaywewalk很好!回答得也不错@是的,现在你不再使用组合(
    nchoosek
    ),它们更相似了,这似乎很有希望。也许再加上一个有两个或三个向量的例子,让这个问题成为一个答案?@LuisMendo。我已经用一个示例代码更新了我的答案,请检查一下并告诉我你对它的看法。这是一个非常好的概括。我认为您已经交换了
    idxB
    idxA
    :它应该是
    [~,idxB]=min(D(:,1));idxA=Idx(idxB)对吗?可能还需要补充的是,所需的最近向量是
    A(idxA,:)
    B(idxB,:)
    @LuisMendo。我目前没有访问MATLAB来检查代码。只要检查
    D
    的大小,如果
    size(D,1)==size(B,1)
    ,那么你是对的,@LuisMendo:我无法破译这个代码。如果您可以访问matlab,请针对我的问题重新发布/更正此代码。
    % A and B could have any Dimension, just same number of columns (signal Dimension)
    A = rand(1000,4);
    B = rand(500,4);
    
    % Use any distance you like, some of them are not supported for KDTreeSearcher,
    % and you should use ExhaustiveSearcher
    myKnnModel= KDTreeSearcher(A, 'Distance', 'minkowski');
    
    % you can ask for many (K) Nearest Neighbors and you always have access to it for later uses
    [Idx, D] = knnsearch(myKnnModel, B, 'K',2);
    
    % and this is answer to your special case
    [~, idxA] = min(D(:, 1))
    idxB = Idx(idxA)