【问题标题】:Count number of values in matrix within given range计算给定范围内矩阵中的值的数量
【发布时间】:2012-08-18 05:57:25
【问题描述】:

我有矩阵

A=[2 3 4 5 6 7;
   7 6 5 4 3 2]

我想统计有多少元素的值大于 3 小于 6。

【问题讨论】:

    标签: matlab matrix


    【解决方案1】:
    flatA = A(:);
    count = sum(flatA > 3 & flatA < 6);
    

    【讨论】:

      【解决方案2】:

      我能想到几个办法:

      count = numel(A( A(:)>3 & A(:)<6 ))      %# (1)
      
      count = length(A( A(:)>3 & A(:)<6 ))     %# (2)
      
      count = nnz( A(:)>3 & A(:)<6 )           %# (3)
      
      count = sum( A(:)>3 & A(:)<6 )           %# (4)
      
      Ac = A(:);
      count = numel(A( Ac>3 & Ac<6 ))          %# (5,6,7,8)
      %# prevents double expansion
      %# similar for length(), nnz(), sum(),
      %# in the same order as (1)-(4)
      
      count = numel(A( abs(A-(6+3)/2)<3/2 ))   %# (9,10,11,12)
      %# prevents double comparison and & 
      %# similar for length(), nnz(), sum()
      %# in the same order as (1)-(4)
      

      那么,让我们测试一下最快的方法是什么。 测试代码:

      A = randi(10, 50);
      tic
      for ii = 1:1e5
      
          %# method is inserted here
      
      end
      toc
      

      结果(最好的 5 次运行,全部以秒为单位):

      %# ( 1): 2.981446
      %# ( 2): 3.006602
      %# ( 3): 3.077083
      %# ( 4): 2.619057
      %# ( 5): 3.011029
      %# ( 6): 2.868021
      %# ( 7): 3.149641
      %# ( 8): 2.457988
      %# ( 9): 1.675575
      %# (10): 1.675384
      %# (11): 2.442607
      %# (12): 1.222510
      

      所以看来count = sum(( abs(A(:)-(6+3)/2)&lt;3/2 )); 是去这里的最佳方式。

      就个人而言:我没想到在 Matlab 中比较会比算术慢——有人知道对此的解释吗?

      另外:为什么nnzsum 慢?我想这是有道理的,因为我知道比较比算术要慢...

      【讨论】:

      【解决方案3】:
      length(A(A>3 & A<6))
      

      【讨论】:

        【解决方案4】:

        Accumarray 是为了做这些事情:

        count = accumarray(A(A>3 & A<6),1)
        

        返回

        >> count'
        ans = 
               0  0  0  2  2
        

        你可以总结:

        count = sum(count);
        

        第一个零对应于我们忽略的 1,2,3 的出现次数。

        甚至更简单:

        count = sum(A(:)>3 & A(:)<6);
        

        【讨论】:

        • accumarray 感觉有点矫枉过正......对于如此复杂的事情来说,问题太简单了。单独的第二个解决方案会给你+1 :)
        • 我在第一次尝试时解释错了问题,后来更正并以 accumarray 为例
        【解决方案5】:

        您可以使用 matlab for-loop 并自行循环遍历这些值。优点是可以指定任何函数(>2 & 3 &

        count = 0;
        for i=1:length(A)
          element = A(i);
          if (element > 2 && element < 5) 
            count = count + 1;
          end
        end
        

        【讨论】:

        • @RodyOldenhuis 这个答案是正确的(虽然不是最短的),因此不应被否决(imo):meta.stackexchange.com/a/130054/185265
        • @GuntherStruyf 在您提供的链接中,在“否决问题”部分:第 2 项“毫无意义”和第 7 项“糟糕的编码实践”当然确实似乎适用在这里。
        • @GuntherStruyf Plus:他的限制是不正确:OP要求&gt;3&lt;6,而分析器包含&gt;2&lt;5。跨度>
        • 这里有什么不好的编码习惯?只有一个分配是不必要的,它确实有意义,优点是可以指定任何函数只有关于限制的第二个参数是有效的 imo
        • @GuntherStruyf 这个解决方案显然源于 C 风格的元素思维,而不是矩阵风格(Matlab 的主要意图)。它教 OP 对每个简单的情况使用循环,而不是更简单的矢量化解决方案。从 OP 的其他帖子中可以推断,他已经习惯使用不需要的循环,这导致 Matlab 中的 bad coding (不,JIT not i> 证明这种循环的合理性)
        猜你喜欢
        • 1970-01-01
        • 2018-07-01
        • 2019-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-22
        相关资源
        最近更新 更多