假设我有两个矢量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)
,相交,重新匹配,但是找不到这些功能可以真正帮助我
答案 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_bin
和b_bin
将无法解析单个bin(那么你必须使用整数类型,再次仔细检查它们的范围就足够了)。带循环的解决方案更安全,但如果你真的需要速度,你可以投资优化所提出的想法。当然,另一种选择是编写一个mex扩展名。
答案 1 :(得分:2)
听起来你要做的就是有一个ismember
函数用于实值数据。
也就是说,检查向量B(i)
中的每个值B
,B(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);