【问题标题】:Test if numpy array contains only zeros测试 numpy 数组是否仅包含零
【发布时间】:2013-08-26 02:03:25
【问题描述】:

我们用零初始化一个 numpy 数组,如下所示:

np.zeros((N,N+1))

但是我们如何检查给定 n*n numpy 数组矩阵中的所有元素是否为零。
如果所有值确实为零,则该方法只需要返回 True。

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    如果你的数组中的所有元素都大于或等于0。我认为使用 sum 是最快的方法。

    test = np.ones((128, 128, 128))
    %%timeit
    not np.any(test)
    >>> 1.46 ms ± 9.09 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    %%timeit
    np.sum(test) == 0
    >>> 646 µs ± 3.19 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    【讨论】:

      【解决方案2】:

      这会起作用。

      def check(arr):
          if np.all(arr == 0):
              return True
          return False
      

      【讨论】:

        【解决方案3】:

        正如另一个答案所说,如果您知道 0 是数组中唯一可能的虚假元素,则可以利用真假评估。一个数组中的所有元素都是假的,如果其中没有任何真元素。*

        >>> a = np.zeros(10)
        >>> not np.any(a)
        True
        

        但是,答案声称any 比其他选项更快,部分原因是短路。截至 2018 年,Numpy 的 allany 不会短路

        如果你经常做这种事情,很容易使用numba制作你自己的短路版本:

        import numba as nb
        
        # short-circuiting replacement for np.any()
        @nb.jit(nopython=True)
        def sc_any(array):
            for x in array.flat:
                if x:
                    return True
            return False
        
        # short-circuiting replacement for np.all()
        @nb.jit(nopython=True)
        def sc_all(array):
            for x in array.flat:
                if not x:
                    return False
            return True
        

        即使没有短路,它们也往往比 Numpy 的版本更快。 count_nonzero 是最慢的。

        检查性能的一些输入:

        import numpy as np
        
        n = 10**8
        middle = n//2
        all_0 = np.zeros(n, dtype=int)
        all_1 = np.ones(n, dtype=int)
        mid_0 = np.ones(n, dtype=int)
        mid_1 = np.zeros(n, dtype=int)
        np.put(mid_0, middle, 0)
        np.put(mid_1, middle, 1)
        # mid_0 = [1 1 1 ... 1 0 1 ... 1 1 1]
        # mid_1 = [0 0 0 ... 0 1 0 ... 0 0 0]
        

        检查:

        ## count_nonzero
        %timeit np.count_nonzero(all_0) 
        # 220 ms ± 8.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
        %timeit np.count_nonzero(all_1)
        # 150 ms ± 4.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        
        ### all
        # np.all
        %timeit np.all(all_1)
        %timeit np.all(mid_0)
        %timeit np.all(all_0)
        # 56.8 ms ± 3.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 57.4 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 55.9 ms ± 2.13 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        
        # sc_all
        %timeit sc_all(all_1)
        %timeit sc_all(mid_0)
        %timeit sc_all(all_0)
        # 44.4 ms ± 2.49 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 22.7 ms ± 599 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 288 ns ± 6.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
        
        ### any
        # np.any
        %timeit np.any(all_0)
        %timeit np.any(mid_1)
        %timeit np.any(all_1)
        # 60.7 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 60 ms ± 287 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 57.7 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        
        # sc_any
        %timeit sc_any(all_0)
        %timeit sc_any(mid_1)
        %timeit sc_any(all_1)
        # 41.7 ms ± 1.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 22.4 ms ± 1.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
        # 287 ns ± 12.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
        

        * 有用的 allany 等价:

        np.all(a) == np.logical_not(np.any(np.logical_not(a)))
        np.any(a) == np.logical_not(np.all(np.logical_not(a)))
        not np.all(a) == np.any(np.logical_not(a))
        not np.any(a) == np.all(np.logical_not(a))
        

        【讨论】:

          【解决方案4】:

          此处发布的其他答案将起作用,但使用最清晰和最有效的功能是numpy.any()

          >>> all_zeros = not np.any(a)
          

          >>> all_zeros = not a.any()
          
          • 这比numpy.all(a==0) 更受欢迎,因为它使用更少的RAM。 (它不需要由 a==0 术语创建的临时数组。)
          • 另外,它比numpy.count_nonzero(a) 更快,因为它可以在找到第一个非零元素时立即返回。
            • 编辑:正如@Rachel 在 cmets 中指出的那样,np.any() 不再使用“短路”逻辑,因此您不会看到小型阵列的速度优势。

          【讨论】:

          • 一分钟前,numpy 的 anyall短路。我相信它们是logical_or.reducelogical_and.reduce 的糖。比较一下我的短路is_inall_false = np.zeros(10**8)all_true = np.ones(10**8)%timeit np.any(all_false) 91.5 ms ± 1.82 ms per loop%timeit np.any(all_true) 93.7 ms ± 6.16 ms per loop%timeit is_in(1, all_true) 293 ns ± 1.65 ns per loop
          • 这点很好,谢谢。看起来短路 used 是一种行为,但在某些时候丢失了。 this question的答案中有一些有趣的讨论。
          【解决方案5】:

          如果您正在测试全零以避免在另一个 numpy 函数上出现警告,则将该行包装在 try, except 块中将省去在您感兴趣的操作之前进行零测试,即

          try: # removes output noise for empty slice 
              mean = np.mean(array)
          except:
              mean = 0
          

          【讨论】:

            【解决方案6】:

            我会在这里使用 np.all,如果你有一个数组 a:

            >>> np.all(a==0)
            

            【讨论】:

            • 我喜欢这个答案也检查非零值。例如,可以通过np.all(a==a[0]) 来检查数组中的所有元素是否相同。非常感谢!
            • 这个方案也比np.count_nonzero效率高一点。 %timeit num_of_non_zeros = np.count_nonzero(zeros_vector) 18.2 µs ± 386 ns 每个循环(平均值 ± 标准偏差。7 次运行,每次 100000 次循环)%timeit num_of_non_zeros = np.all((zeros_vector == 0)) 7.31 µs ±每个循环 41.6 ns(平均值 ± 标准偏差。7 次运行,每次 100000 次循环)
            【解决方案7】:

            查看numpy.count_nonzero

            >>> np.count_nonzero(np.eye(4))
            4
            >>> np.count_nonzero([[0,1,7,0,0],[3,0,0,2,19]])
            5
            

            【讨论】:

            • 只有当所有值都为 0 时,您才会希望 not np.count_nonzero(np.eye(4)) 返回 True
            • array.nonzero()[0].size == 0 在实践中往往更快
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-02-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-10-16
            相关资源
            最近更新 更多