在Matlab中工作我有2个不同长度的x坐标向量。例如:
xm = [15 20 24 25 26 35 81 84 93];
xn = [14 22 26 51 55 59 70 75 89 96];
我需要将xm映射到xn,或者换句话说,找到xn中哪些坐标最接近xm。因此,如果我有与这些坐标相关联的值,我可以将此地图用作索引并关联这些值。
两个向量都已排序,每个向量中没有重复。
我用for循环写了一个简单的函数:
function xmap = vectors_map(xm,xn)
xmap = zeros(size(xm));
for k=1:numel(xm)
[~, ind] = min(abs(xm(k)-xn));
xmap(k) = ind(1);
end
上面的例子是返回
xmap =
1 2 2 3 3 3 8 9 10
它工作正常,但需要一段时间才能使用长矢量(超过100,000点)。
有关如何对此代码进行矢量化的任何想法吗?
答案 0 :(得分:5)
哦!另一个选择:既然你正在寻找两个排序列表之间的密切对应关系,你可以使用类似合并的算法同时浏览它们。这应该是O(max(长度(xm),长度(xn))) - ish。
match_for_xn = zeros(length(xn), 1);
last_M = 1;
for N = 1:length(xn)
% search through M until we find a match.
for M = last_M:length(xm)
dist_to_curr = abs(xm(M) - xn(N));
dist_to_next = abs(xm(M+1) - xn(N));
if dist_to_next > dist_to_curr
match_for_xn(N) = M;
last_M = M;
break
else
continue
end
end % M
end % N
编辑: 看@ yuk的评论,上面的代码并不完全正确!
答案 1 :(得分:4)
考虑这个矢量化解决方案:
[~, xmap] = min( abs(bsxfun(@minus, xm, xn')) )
答案 2 :(得分:3)
我知道解决这个问题的最快实现是this one(可以编译为.mex文件的C代码;对我来说,它比接受答案中的rescdsk代码快20倍)。令人惊讶的是,这种常见操作不是MATLAB内置函数。
答案 3 :(得分:1)
看起来您的输入向量已排序。使用二进制搜索查找最接近的匹配项。这将为您提供O(n ln n)运行时间。
答案 4 :(得分:0)
您的xm和xn已排序。如果通常是这种情况,那么你可以比跨越整个阵列做得更好。
对于xn中的每个值,将存在一系列值,xm中的值将比任何其他值更接近该值。事先计算这些间隔,然后按顺序逐步浏览两个数组。
答案 5 :(得分:0)
正如大卫所说,利用被排序的优势会更快,因为你有这么多的积分,但作为参考,一种方法来矢量化这将是使用meshgrid:
[X Y] = meshgrid(xn, xm);
diffs = X - y;
mins = min(diffs, [], 2);
请注意,这将在内存中创建两个100,000 x 100,000个数组,因此它可能仅适用于较小的数据集。