在两个矩阵matlab中查找最接近(不相等)的行

时间:2014-02-25 20:06:48

标签: matlab closest-points

我有两个矩阵A(m X 3)和B(n X 3);其中m>> Ñ

B中的数字与A中的数字具有接近或相等的值。

我想搜索A中最接近的可能值到B中存在的值,以便在搜索结束时,A将减少到(n X 3)。

有两个主要问题:

  1. 只有A中的完整行可以与B中的完整行进行比较,其中A和B的每列中的数字是独立变化的。
  2. A和B中的数字可能与十进制的第三位(例如20.101和20.103)一样接近
  3. 我希望我能够清楚地提出我的问题。 有没有人知道matlab中已存在的任何函数?

3 个答案:

答案 0 :(得分:4)

根据您对任务的看法,这里有两种不同的方法

第二个矩阵中每行的最小距离

两种观察方式:(1)AB中每个点的最近点,或B中{(1}}中A中每个点的最近点{{1} }}

A

中的最近点

对于B中的每个点,您可以按照评论中的要求找到A中的最近点(例如欧几里德距离):

% Calculate all MxN high-dimensional (3D space) distances at once
distances = squeeze(sum(bsxfun(@minus,B,permute(A,[3 2 1])).^2,2));

% Find closest row in A for each point in B
[~,ik] = min(distances,[],2)

制作一个大小为B的数组,其中包含A中最近的点:

Anew = A(ik,:)

只要A中的每个点在B中都匹配,这将隐含地抛弃B中与A中的点相距太远的任何点。如果B中的每个点在A中不一定具有“匹配”(指向可接受的距离),则必须根据distances主动拒绝点,从而导致输出短于B 。这个解决方案似乎超出了范围。

B

中的最近点

计算从A中的每个点(行)到B中每个点的欧几里德距离,并确定B中的最近点:

distances = squeeze(sum(bsxfun(@minus,A,permute(B,[3 2 1])).^2,2));
[~,ik] = min(distances,[],2)

制作一个大小为A的数组,其中包含B中最近的点:

Anew = B(ik,:)

此方法中Anew的大小与A相同。

合并第一张矩阵中的相似点

另一种方法是使用undocumented _mergesimpts function

考虑这个测试数据:

>> B = randi(5,4,3)
B =
     1     4     4
     2     3     4
     1     3     4
     3     4     5
>> tol = 0.001;
>> A = repmat(B,3,1) + tol * rand(size(B,1)*3,3)
A =
    1.0004    4.0005    4.0000
    2.0004    3.0005    4.0008
    1.0004    3.0009    4.0002
    3.0008    4.0005    5.0004
    1.0006    4.0004    4.0007
    2.0008    3.0007    4.0004
    1.0009    3.0007    4.0007
    3.0010    4.0005    5.0004
    1.0002    4.0003    4.0007
    2.0001    3.0001    4.0007
    1.0007    3.0006    4.0004
    3.0001    4.0003    5.0000

根据指定的容差A合并tol中的相似行:

>> builtin('_mergesimpts',A,tol,'average')
ans =
    1.0004    4.0004    4.0005
    1.0007    3.0007    4.0005
    2.0005    3.0005    4.0006
    3.0006    4.0004    5.0003

合并相似的行,使用B获取预期的数字

>> builtin('_mergesimpts',[A; B],tol,'first')
ans =
     1     3     4
     1     4     4
     2     3     4
     3     4     5

答案 1 :(得分:1)

A的每一行替换为B的最近一行

您可以使用pdist2计算行之间的距离,然后使用min的第二个输出来查找最小距离行的索引:

[~, ind] = min(pdist2(B,A,'euclidean')); %// or specify some other distance
result = B(ind,:);

这种方法的优点是pdist2允许您指定其他距离函数,甚至可以定义自己的距离函数。例如,要使用L1 distance将第一行更改为

[~, ind] = min(pdist2(B,A,'cityblock'));

保留最接近A

行的B

如上所述使用pdist2。对于A的每一行,计算B行的最小距离。保留nA的最小距离值

[~, ii] = sort(min(pdist2(B,A,'euclidean'))); %// or use some other distance
result = A(ii(1:n),:);

答案 2 :(得分:0)

试试这段代码 -

%% Create data
m=7;
n=4;
TOL = 0.0005;

A = rand(m,3)/100;
B = rand(n,3)/100;
B(2,:) = A(5,:); % For testing that the matching part of the second row from B must be the fifth row from A

%% Interesting part
B2 = repmat(reshape(B',1,3,n),[m 1]);
closeness_matrix = abs(bsxfun(@minus, A, B2));
closeness_matrix(closeness_matrix<TOL)=0;
closeness_matrix_mean = mean(closeness_matrix,2);  % Assuming that the "closeness" for the triplets on each row can be measured by the mean value of them
X1 = squeeze(closeness_matrix_mean);

[minval,minind] = min(X1,[],1);
close_indices = minind';

A_final = A(close_indices,:)