【问题标题】:How to find number of occurrences of a subset of elements in a vector without using loops in MATLAB?如何在不使用MATLAB中的循环的情况下查找向量中元素子集的出现次数?
【发布时间】:2017-02-22 22:06:04
【问题描述】:

说 X 是给定的向量:

   X=[1
      2
      4
      2
      3
      1
      4
      5
      2
      4
      5];

Y 是 X 中元素的给定子集:

Y=[3
   4
   5];

所需的输出是 Y 中的元素在 X 中出现的次数:

out=[1
     3
     2];

我的解决方案是使用for 循环:

for i=1:size(X,1)
    temp = X(X(:,1)==Y(i,1),:);
    out(i,1) = size(temp,1);
end

但是当 X 和 Y 很大时,这是低效的。那么,如何利用矢量化更快地做到这一点呢?我知道histhistc,但我想不出在这种情况下如何使用它们来获得所需的输出。

【问题讨论】:

    标签: matlab frequency


    【解决方案1】:

    快速选择

    您可以使用bsxfun 结合sum 来计算这个

    sum(bsxfun(@eq, Y, X.'), 2)
    

    说明

    在此示例中,bsxfunXY 中的每个元素组合执行给定操作。我们要使用的操作是eq(相等性检查)。结果是一个矩阵,Y 中的每个元素都有一行,X 中的每个元素都有一个列。如果X 中的元素等于Y 中对应于给定行的元素,它将具有1 值。

    bsxfun(@eq, Y, X.')
    
    %    0     0     0     0     1     0     0     0     0     0     0
    %    0     0     1     0     0     0     1     0     0     1     0
    %    0     0     0     0     0     0     0     1     0     0     1
    

    然后我们可以对列求和,以计算X 中等于Y 中给定值的元素数量。

    sum(bsxfun(@eq, Y, X.'), 2)
    
    %   1
    %   3
    %   2
    

    在较新版本的 MATLAB(自 R2016b 起)上,您可以省略 bsxfun,因为相等操作会自动广播。

    sum(Y - X.', 2)
    

    一种节省内存的选项

    第一个选项不是最有效的,因为它需要创建一个 [numel(Y), numel(X)] 元素大的矩阵。另一种可能更节省内存的方法可能是将ismember 的第二个输出与 accumarray 结合使用

    [tf, ind] = ismember(X, Y);
    counts = accumarray(ind(tf), ones(sum(tf), 1), [numel(Y), 1], @numel);
    

    说明

    ismember 用于确定一个数组中的值是否在另一个数组中。第一个输入告诉我们 if 第一个输入的每个元素都在第二个输入中,第二个输出告诉你 在第二个输入中的哪里 第一个输入的每个元素都被找到.

    [tf, ind] = ismember(X, Y);
    
    %   0 0 1 0 1 0 1 1 0 1 1
    %   0 0 2 0 1 0 2 3 0 2 3
    

    我们可以使用第二个输入将相同的值“分组”在一起。 accumarray 函数正是这样做的,它使用上面的ind 变量来确定组,然后将给定的操作应用于每个组。在我们的例子中,我们想简单地确定每个组中元素的数量。因此,我们可以传递第二个输入,其大小为 ind 输入(减去不匹配的那些),然后使用 numel 作为操作(计算每组中的数量)

    counts = accumarray(ind(tf), ones(sum(tf), 1), [numel(Y), 1], @numel);
    
    %   1
    %   3
    %   2
    

    【讨论】:

    • @Kristada673 XY 有多大?
    • 相当大。 X 有 588 万行,Y 有 110 万行。
    • @Kristada673 哎呀!试试我刚刚发布的第二个选项,看看效果是否更好。
    • 哇!那行得通!您能否像在第一个选项中那样提供解释?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 2013-10-24
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    相关资源
    最近更新 更多