Matlab:比较两个不同长度和不同值的向量?

时间:2013-07-12 09:50:57

标签: matlab

假设我有两个矢量A和B,长度不同Length(A) is not equal to Length(B),矢量A中的值与矢量B中的值不同。我想比较B的每个值和A的值(比较表示如果值B(i)几乎与A(1:end)的值相同,例如B(i)-Tolerance<A(i)<B(i)+Tolerance

如果不使用for loop,我怎么能这样做,因为数据很大?

我知道ismember(F),相交,重新匹配,但是找不到这些功能可以真正帮助我

5 个答案:

答案 0 :(得分:3)

您可以尝试这些方面的解决方案:

tol = 0.1; 

N = 1000000; 

a = randn(1, N)*1000; % create a randomly

b = a + tol*rand(1, N); % b is "tol" away from a

a_bin = floor(a/tol); 
b_bin = floor(b/tol); 

result = ismember(b_bin, a_bin) | ...
         ismember(b_bin, a_bin-1) | ...
         ismember(b_bin, a_bin+1); 

find(result==0) % should be empty matrix. 

我们的想法是将a和b变量离散化为大小为tol的二进制数。然后,您询问b是否与a中的任何元素位于同一个bin中,或者位于其左侧的bin中,或者位于其右侧的bin中。

优势:我认为ismember内部很聪明,首先对a的元素进行排序,然后对每个元素b执行次线性(log(N))搜索。这与使用a中的元素明确地构造b中的每个元素的差异的方法不同,这意味着复杂性在a中的元素数量是线性的。

比较:对于N=100000,我在我的机器上运行0.04秒,相比之下使用线性搜索运行20秒(使用Alan简洁明了的tf = arrayfun(@(bi) any(abs(a - bi) < tol), b);解决方案计时)。

缺点:这导致实际公差在tol和1.5 * tol之间。取决于你的任务是否可以忍受(如果唯一的关注点是浮点比较,你可以)。

注意:这是否可行取决于a和b的范围以及tol的值。如果a和b可能非常大并且tol非常小,a_binb_bin将无法解析单个bin(那么你必须使用整数类型,再次仔细检查它们的范围就足够了)。带循环的解决方案更安全,但如果你真的需要速度,你可以投资优化所提出的想法。当然,另一种选择是编写一个mex扩展名。

答案 1 :(得分:2)

听起来你要做的就是有一个ismember函数用于实值数据。

也就是说,检查向量B(i)中的每个值BB(i)是否在向量{{1}中的至少一个值的容差阈值T内}}

这可以解决以下问题:

A

或者,简而言之:

tf = false(1, length(b)); %//the result vector, true if that element of b is in a
t = 0.01; %// the tolerance threshold
for i = 1:length(b)
    %// is the absolute difference between the 
    %//element of a and b less that the threshold?
    matches = abs(a - b(i)) < t; 

    %// if b(i) matches any of the elements of a
    tf(i) = any(matches);
end

关于避免for循环:虽然这可能会受益于矢量化,但如果您的数据 那么,您可能还需要考虑并行化。在这种情况下,在我的第一个示例中使用for循环可以很方便,因为您可以通过将t = 0.01; tf = arrayfun(@(bi) any(abs(a - bi) < t), b); 更改为for来轻松执行基本版本的并行处理。

答案 2 :(得分:1)

这是一个完全矢量化的解决方案。请注意,我实际上会推荐@Alan给出的解决方案,因为我的大数据集不太可能。

[X Y]=meshgrid(A,B)
M=abs(X-Y)<tolerance 

现在可以使用any(M)获取a在容差范围内的元素的逻辑索引,并且any(M,2)找到B的索引

答案 3 :(得分:1)

bsxfun救援

 >> M = abs( bsxfun(@minus, A, B' ) ); %//' difference
 >> M < tolerance 

答案 4 :(得分:0)

另一种做你想做的事的方法是使用逻辑表达式 由于A和B是不同大小的向量,因此您不能简单地减去并查找小于公差的值,但您可以执行以下操作:

Lmat = sparse((abs(repmat(A,[numel(B) 1])-repmat(B',[1 numel(A)])))<tolerance);

你会得到一个稀疏的逻辑矩阵,其中包含相同元素(在容差范围内)。然后,您可以通过编写来计算这些元素的数量:

Nequal = sum(sum(Lmat));

您还可以通过编写以下内容来获取相应元素的索引:

[r,c] = find(Lmat);

然后以下代码为真(对于numel(r)中的所有j):

B(r(j))==A(c(j))

最后,您应该注意,如果A或B中存在重复条目,您可以通过这种方式获得多个计数。建议首先使用unique函数。例如:

A_new = unique(A);