如何在NumPy布尔数组中计算真实元素的数量

242

我有一个布尔类型的NumPy数组'boolarr'。 我想计算其值为True的元素数量。是否有专门用于此任务的NumPy或Python例程?还是说我需要在脚本中迭代这些元素?


4
对于 pandas:https://dev59.com/questions/qV8e5IYBdhLWcg3wHnks本文介绍了如何在 Python 中使用 Pandas 计算 DataFrame 每列中非零值的数量。 - Private
6个回答

343

你有多种选择。以下是其中两个。

boolarr.sum()
numpy.count_nonzero(boolarr)

这里有一个例子:

>>> import numpy as np
>>> boolarr = np.array([[0, 0, 1], [1, 0, 1], [1, 0, 1]], dtype=np.bool)
>>> boolarr
array([[False, False,  True],
       [ True, False,  True],
       [ True, False,  True]], dtype=bool)

>>> boolarr.sum()
5

当然,那是一个针对 bool 类型的答案。更普遍地,您可以使用 numpy.count_nonzero

>>> np.count_nonzero(boolarr)
5

3
谢谢,David。它们看起来很整洁。关于使用sum(..)的方法,在Python中(或至少在NumPy中),True是否总是等于1?如果不能保证,我会先添加一个检查'if True==1:'。关于count_nonzero(..),不幸的是,在我使用的NumPy版本1.5.1中没有实现它,但将来我可能有机会使用它。 - norio
5
关于 bool:在算术运算中,布尔值会被视为 1 和 0。请参阅 Python 标准库文档中的“布尔值”部分。请注意,NumPy 的 bool 类型和 Python 的 bool 类型不同,但是它们是兼容的(更多信息请参见此处)。 - David Alber
1
@norio 关于 NumPy v1.5.1 中没有 numpy.count_nonzero 的问题:你说得对。根据这个发布公告,它是在 NumPy v1.6.0 中添加的。 - David Alber
31
就我个人的Python解释器而言,numpy.count_nonzero 至少比 sum 快了一千倍。以下是两种方法的代码及其性能测试结果: 使用 numpy.count_nonzeroimport numpy as np bools = np.random.uniform(size=1000) >= 0.5 np.count_nonzero(bools)使用 sumimport numpy as np bools = np.random.uniform(size=1000) >= 0.5 sum(bools)其中,性能测试代码如下:python -m timeit -s "import numpy as np; bools = np.random.uniform(size=1000) >= 0.5" "np.count_nonzero(bools)" python -m timeit -s "import numpy as np; bools = np.random.uniform(size=1000) >= 0.5" "sum(bools)" - chbrown
10
@chbrown 你是对的。但是你应该与 np.sum(bools) 进行比较!然而,np.count_nonzero(bools) 仍然要快大约12倍。 - mab
显示剩余4条评论

33

这个问题解决了我一个非常相似的问题,我认为应该分享一下:

在原生的 Python 中,你可以使用 sum() 统计 listTrue 的值:

>>> sum([True,True,True,False,False])
3

但这样做是行不通的:

>>> sum([[False, False, True], [True, False, True]])
TypeError...

2
你应该先“展平”数组。不幸的是,没有内置方法,请参见https://dev59.com/THI95IYBdhLWcg3wyBCc。 - tommy chheng
2
谢谢Guillaume!也适用于Pandas数据框。 - JJFord3
Pandas DataFrame和numpy数组的原始内置sum比它们各自的sum方法慢得多。 - Elias Hasle

5

在比较两个numpy数组并计算匹配数(例如机器学习中的正确类别预测)方面,我发现下面的两个维度的示例很有用:

import numpy as np
result = np.random.randint(3,size=(5,2)) # 5x2 random integer array
target = np.random.randint(3,size=(5,2)) # 5x2 random integer array

res = np.equal(result,target)
print result
print target
print np.sum(res[:,0])
print np.sum(res[:,1])

这可以扩展到D维。

结果如下:

预测:

[[1 2]
 [2 0]
 [2 0]
 [1 2]
 [1 2]]

目标:

[[0 1]
 [1 0]
 [2 0]
 [0 0]
 [2 1]]

D=1时正确预测的数量为:1

D=2时正确预测的数量为:2


2
b[b].size

其中 b 是需要处理的布尔值 ndarray。它会将 b 过滤为 True,然后计算过滤后数组的长度。

这种方法可能不如之前提到过的 np.count_nonzero() 效率高,但如果你忘记了其他语法,它仍然很有用。此外,这种更短的语法可以节省程序员的时间。

示例:

In [1]: a = np.array([0,1,3])

In [2]: a
Out[2]: array([0, 1, 3])

In [3]: a[a>=1].size
Out[3]: 2

In [5]: b=a>=1

In [6]: b
Out[6]: array([False,  True,  True])

In [7]: b[b].size
Out[7]: 2

0

对于一维数组,这是我使用的方法:

import numpy as np
numbers= np.array([3, 1, 5, 2, 5, 1, 1, 5, 1, 4, 2, 1, 4, 5, 3, 4, 
                  5, 2, 4, 2, 6, 6, 3, 6, 2, 3, 5, 6, 5])

numbersGreaterThan2= np.count_nonzero(numbers> 2)

0
boolarr.sum(axis=1 or axis=0)

axis = 1 将输出一行中 True 的数量,而 axis = 0 将计算列中 True 的数量。

boolarr[[true,true,true],[false,false,true]]
print(boolarr.sum(axis=1))

将会是 (3,1)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接