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

Matlab:比较两个不同长度和不同值的向量?,matlab,Matlab,假设我有两个不同长度的向量A和BLength(A)不等于Length(B),向量A中的值与向量B中的值不同。我想将B的每个值与A的值进行比较(比较意味着如果值B(I)几乎与A(1:end)的值相同,例如B(I)-Tolerance听起来您想要做的是在实值数据上使用一个ismember函数 也就是说,检查向量B(i)中的每个值B(i)是否在向量A中至少一个值的公差阈值T内 其结果如下所示: tf = false(1, length(b)); %//the result vector, true i

假设我有两个不同长度的向量A和B
Length(A)不等于Length(B)
,向量A中的值与向量B中的值不同。我想将B的每个值与A的值进行比较(比较意味着如果值B(I)几乎与
A(1:end)
的值相同,例如
B(I)-Tolerance听起来您想要做的是在实值数据上使用一个
ismember
函数

也就是说,检查向量
B(i)
中的每个值
B(i)
是否在向量
A
中至少一个值的公差阈值
T

其结果如下所示:

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
Lmat = sparse((abs(repmat(A,[numel(B) 1])-repmat(B',[1 numel(A)])))<tolerance);
tf=false(1,长度(b));%//结果向量,如果b的元素在a中,则为true
t=0.01;%//公差阈值
对于i=1:长度(b)
%//两者之间的绝对差异是多少
%//a和b元素小于阈值?
匹配项=abs(a-b(i))
或者,简而言之:

t = 0.01;
tf = arrayfun(@(bi) any(abs(a - bi) < t), b);
t=0.01;
tf=arrayfun(@(bi)any(abs(a-bi)

关于避免循环的问题:虽然这可能得益于向量化,但是如果你的数据是巨大的,你也可能想考虑并行化。在这种情况下,在我的第一个例子中有一个for循环是很方便的,因为你可以很容易地通过改变< <代码> < <代码> > <代码> PAROF<代码,来执行并行处理的基本版本。>.

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

[X Y]=meshgrid(A,B)
M=abs(X-Y)<tolerance 
[xy]=meshgrid(A,B)
M=abs(X-Y)用于救援

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

您可以尝试以下解决方案:

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中的任何元素位于同一容器中,或位于其左侧的容器中,或位于其右侧的容器中

优点:我相信
ismember
内部很聪明,首先对
a
的元素进行排序,然后执行次线性(log(N))按元素b搜索。这不同于显式构造b中的每个元素与a中的元素之间的差异的方法,这意味着复杂性在a中的元素数量上是线性的

比较:对于
N=100000
,这在我的机器上运行0.04秒,而使用线性搜索(使用Alan的漂亮简洁的
tf=arrayfun(@(bi)any(abs(a-bi)
解决方案)运行20秒

缺点:这导致实际公差介于tol和1.5*tol之间。这取决于您的任务,您是否能够接受(如果唯一关心的是浮点比较,您可以)


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

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

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
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):

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

A_new = unique(A);

所以你只是比较
A(i)
B(i)
?为什么不发布现有的for循环代码,人们也许可以从中提出改进建议。这是一个针对ismember的解决方案,具有容差。它的速度大约是@ondav发布的解决方案的两倍,但处理容差更准确。不错,但它显式存储元素对差异-内存复杂性
M*N
。我喜欢这个,它非常好而且简单,解决了任务。唯一的问题是
any
中的线性搜索-查看我的解决方案和执行时间比较。不确定它会对性能产生什么影响,但您是否考虑过将_bin+-1组合起来,这样您只需要一个ismember?是的,您可以,我相信它会ld速度更快,因为只有1个内部排序。好提示!@DennisJaheruddin尝试过-是的,这将时间从0.05秒减少到了0.04秒。@ondav这是一种很好的快速方法。关于装箱方法,您是否考虑过将数字相乘,使您感兴趣的部分为整数?即:
a_-bin=四舍五入(a.*10);
精确到小数点后1位,因此公差为0.1。@Alan是的,它实际上发生在这里:
a_-bin=地板(a/tol);