1

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

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

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

主要有两个问题:

  1. 只有 A 中的完整行可以与 B 中的完整行进行比较,其中 A 和 B 的每一列中的数字独立变化。
  2. A 和 B 中的数字可能接近小数点后第三位(例如 20.101 和 20.103)

我希望我能清楚地提出我的问题。有人知道matlab中已经存在的任何函数吗?

4

3 回答 3

4

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

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

有两种方法来看待这个问题:(1) 中A每个点的最近点B,或 (2) 中B每个点的最近点A

最近的点在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,:)

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

最近的点在B

A计算从 in 中的每个点(行)到 in中的每个点的欧几里得距离,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

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

另一种方法是使用未记录的_mergesimpts函数

考虑这个测试数据:

>> 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
于 2014-02-25T21:05:22.800 回答
1

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

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

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

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

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

保留A最接近的行B

使用pdist2如上。对于每一行A计算到 的行的最小距离B。保留具有该最小距离最小值的n行:A

[~, ii] = sort(min(pdist2(B,A,'euclidean'))); %// or use some other distance
result = A(ii(1:n),:);
于 2014-02-25T21:39:42.610 回答
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,:)
于 2014-02-25T21:05:12.443 回答