【问题标题】:Counting the number of non-NaN elements in a numpy ndarray in Python在 Python 中计算 numpy ndarray 中非 NaN 元素的数量
【发布时间】:2014-03-13 17:46:50
【问题描述】:

我需要计算 numpy ndarray 矩阵中非 NaN 元素的数量。如何在 Python 中有效地做到这一点?这是我实现此目的的简单代码:

import numpy as np

def numberOfNonNans(data):
    count = 0
    for i in data:
        if not np.isnan(i):
            count += 1
    return count 

numpy 中是否有内置函数?效率很重要,因为我正在做大数据分析。

感谢您的帮助!

【问题讨论】:

  • 这个问题似乎是题外话,因为它属于codereview.stackexchange.com
  • 你的意思是在内存方面高效?
  • +1 我在考虑 CPU 时间,但是为什么不考虑内存。越快越便宜越好 =)
  • @jjepsuomi 内存效率高的版本是sum(not np.isnan(x) for x in a),但就速度而言,它比@M4rtini numpy 版本慢。
  • @AshwiniChaudhary 非常感谢!我需要看看在我的应用程序中哪个更重要 =)

标签: python numpy matrix nan


【解决方案1】:
np.count_nonzero(~np.isnan(data))

~ 反转从np.isnan 返回的布尔矩阵。

np.count_nonzero 计算不为 0\false 的值。 .sum 应该给出相同的结果。但也许更清楚地使用count_nonzero

测试速度:

In [23]: data = np.random.random((10000,10000))

In [24]: data[[np.random.random_integers(0,10000, 100)],:][:, [np.random.random_integers(0,99, 100)]] = np.nan

In [25]: %timeit data.size - np.count_nonzero(np.isnan(data))
1 loops, best of 3: 309 ms per loop

In [26]: %timeit np.count_nonzero(~np.isnan(data))
1 loops, best of 3: 345 ms per loop

In [27]: %timeit data.size - np.isnan(data).sum()
1 loops, best of 3: 339 ms per loop

data.size - np.count_nonzero(np.isnan(data)) 似乎几乎不是这里最快的。其他数据可能会给出不同的相对速度结果。

【讨论】:

  • +1 @M4rtini 再次感谢您!你很棒! ;D 我会尽快接受你的回答 :)
  • 甚至numpy.isnan(array).sum()?不过,我对 numpy 不是很精通。
  • @msvalkon,它将计算 NaN 的数量,而 OP 想要非 NaN 元素的数量。
  • @msvalkon 答案的扩展:data.size - np.isnan(data).sum() 会稍微高效一些。
【解决方案2】:

另一种选择,但速度稍慢一些,是通过索引来完成。

np.isnan(data)[np.isnan(data) == False].size

In [30]: %timeit np.isnan(data)[np.isnan(data) == False].size
1 loops, best of 3: 498 ms per loop 

np.isnan(data)== 运算符的双重使用可能有点矫枉过正,所以我发布答案只是为了完整性。

【讨论】:

    【解决方案3】:

    快速编写替代方案

    即使不是最快的选择,但如果性能不是问题,您可以使用:

    sum(~np.isnan(data)).

    性能:

    In [7]: %timeit data.size - np.count_nonzero(np.isnan(data))
    10 loops, best of 3: 67.5 ms per loop
    
    In [8]: %timeit sum(~np.isnan(data))
    10 loops, best of 3: 154 ms per loop
    
    In [9]: %timeit np.sum(~np.isnan(data))
    10 loops, best of 3: 140 ms per loop
    

    【讨论】:

    • 这个答案提供了与计算元素数量不同的总和......您应该改用len
    • @BenT 满足特定条件的布尔数组元素的总和与为子集数组的 len 提供满足特定条件的元素相同。你能澄清这是哪里错了吗?
    • 我的错误我忘记了一个布尔值得到了回报。
    【解决方案4】:

    判断数组是否稀疏,获取一定比例的nan值可能会有所帮助

    np.isnan(ndarr).sum() / ndarr.size
    

    如果该比例超过阈值,则使用稀疏数组,例如 - https://sparse.pydata.org/en/latest/

    【讨论】:

      猜你喜欢
      • 2015-10-08
      • 2022-11-07
      • 2018-03-16
      • 2016-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-02-01
      • 2015-10-08
      相关资源
      最近更新 更多