我有两个矩阵A(m X 3)和B(n X 3);其中m>> Ñ
B中的数字与A中的数字具有接近或相等的值。
我想搜索A中最接近的可能值到B中存在的值,以便在搜索结束时,A将减少到(n X 3)。
有两个主要问题:
我希望我能够清楚地提出我的问题。 有没有人知道matlab中已存在的任何函数?
答案 0 :(得分:4)
根据您对任务的看法,这里有两种不同的方法
两种观察方式:(1)A
中B
中每个点的最近点,或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
行的最小距离。保留n
行A
的最小距离值
[~, 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,:)