在Python中,我有一个ndarray y
打印为array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
我试图计算这个数组中有多少个0
和多少个1
。
但是当我输入y.count(0)
or时y.count(1)
,它说
numpy.ndarray
对象没有属性count
我该怎么办?
numpy.count_nonzero
。
在Python中,我有一个ndarray y
打印为array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
我试图计算这个数组中有多少个0
和多少个1
。
但是当我输入y.count(0)
or时y.count(1)
,它说
numpy.ndarray
对象没有属性count
我该怎么办?
numpy.count_nonzero
。
Answers:
>>> a = numpy.array([0, 3, 0, 1, 0, 1, 2, 1, 0, 0, 0, 0, 1, 3, 4])
>>> unique, counts = numpy.unique(a, return_counts=True)
>>> dict(zip(unique, counts))
{0: 7, 1: 4, 2: 1, 3: 2, 4: 1}
非numpy方式:
>> import collections, numpy
>>> a = numpy.array([0, 3, 0, 1, 0, 1, 2, 1, 0, 0, 0, 0, 1, 3, 4])
>>> collections.Counter(a)
Counter({0: 7, 1: 4, 3: 2, 2: 1, 4: 1})
dict(zip(*numpy.unique(a, return_counts=True)))
collections.Counter
效果很好
那使用numpy.count_nonzero
什么呢
>>> import numpy as np
>>> y = np.array([1, 2, 2, 2, 2, 0, 2, 3, 3, 3, 0, 0, 2, 2, 0])
>>> np.count_nonzero(y == 1)
1
>>> np.count_nonzero(y == 2)
7
>>> np.count_nonzero(y == 3)
3
numpy.ndarray
像OP最初要求的那样有效。
就个人而言,我会去:
(y == 0).sum()
和(y == 1).sum()
例如
import numpy as np
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
num_zeros = (y == 0).sum()
num_ones = (y == 1).sum()
sum( vector==value )
对于您的情况,您还可以查看numpy.bincount
In [56]: a = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
In [57]: np.bincount(a)
Out[57]: array([8, 4]) #count of zeros is at index 0 : 8
#count of ones is at index 1 : 4
将数组转换y
为列表l
,然后执行l.count(1)
和l.count(0)
>>> y = numpy.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
>>> l = list(y)
>>> l.count(1)
4
>>> l.count(0)
8
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
如果你知道,他们只是0
和1
:
np.sum(y)
给你的数量。 np.sum(1-y)
给出零。
为了稍微概括起见,如果要计数0
而不是零(但可能是2或3):
np.count_nonzero(y)
给出非零的数量。
但是,如果您需要更复杂的东西,我认为numpy不会提供一个不错的count
选择。在这种情况下,请转到集合:
import collections
collections.Counter(y)
> Counter({0: 8, 1: 4})
这就像一个字典
collections.Counter(y)[0]
> 8
老实说,我发现将其转换为pandas系列或DataFrame最简单:
import pandas as pd
import numpy as np
df = pd.DataFrame({'data':np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])})
print df['data'].value_counts()
或罗伯特·穆伊(Robert Muil)提出的这一好话:
pd.Series([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]).value_counts()
pd.Series([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]).value_counts()
没有人建议使用numpy.bincount(input, minlength)
带minlength = np.size(input)
,但它似乎是一个很好的解决方案,并且绝对是最快的:
In [1]: choices = np.random.randint(0, 100, 10000)
In [2]: %timeit [ np.sum(choices == k) for k in range(min(choices), max(choices)+1) ]
100 loops, best of 3: 2.67 ms per loop
In [3]: %timeit np.unique(choices, return_counts=True)
1000 loops, best of 3: 388 µs per loop
In [4]: %timeit np.bincount(choices, minlength=np.size(choices))
100000 loops, best of 3: 16.3 µs per loop
numpy.unique(x, return_counts=True)
和之间的疯狂加速numpy.bincount(x, minlength=np.max(x))
!
np.histogram
不计算相同的内容。histogram
抱歉,我没有将我建议的三种方法与函数进行比较。
bincount
只适用于整数,因此它适用于OP的问题,但不适用于标题中所述的一般性问题。您是否也尝试过使用bincount
具有很大整数的数组?
bincount
上的速度比机器快四倍unique
。
要计算出现次数,可以使用np.unique(array, return_counts=True)
:
In [75]: boo = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
# use bool value `True` or equivalently `1`
In [77]: uniq, cnts = np.unique(boo, return_counts=1)
In [81]: uniq
Out[81]: array([0, 1]) #unique elements in input array are: 0, 1
In [82]: cnts
Out[82]: array([8, 4]) # 0 occurs 8 times, 1 occurs 4 times
利用系列提供的方法:
>>> import pandas as pd
>>> y = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]
>>> pd.Series(y).value_counts()
0 8
1 4
dtype: int64
一个简单的一般答案是:
numpy.sum(MyArray==x) # sum of a binary list of the occurence of x (=0 or 1) in MyArray
这将导致完整的代码作为示例
import numpy
MyArray=numpy.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]) # array we want to search in
x=0 # the value I want to count (can be iterator, in a list, etc.)
numpy.sum(MyArray==0) # sum of a binary list of the occurence of x in MyArray
现在,如果MyArray具有多个维度,并且您要计算行中值分布的出现次数(此后为pattern)
MyArray=numpy.array([[6, 1],[4, 5],[0, 7],[5, 1],[2, 5],[1, 2],[3, 2],[0, 2],[2, 5],[5, 1],[3, 0]])
x=numpy.array([5,1]) # the value I want to count (can be iterator, in a list, etc.)
temp = numpy.ascontiguousarray(MyArray).view(numpy.dtype((numpy.void, MyArray.dtype.itemsize * MyArray.shape[1]))) # convert the 2d-array into an array of analyzable patterns
xt=numpy.ascontiguousarray(x).view(numpy.dtype((numpy.void, x.dtype.itemsize * x.shape[0]))) # convert what you search into one analyzable pattern
numpy.sum(temp==xt) # count of the searched pattern in the list of patterns
对于通用条目:
x = np.array([11, 2, 3, 5, 3, 2, 16, 10, 10, 3, 11, 4, 5, 16, 3, 11, 4])
n = {i:len([j for j in np.where(x==i)[0]]) for i in set(x)}
ix = {i:[j for j in np.where(x==i)[0]] for i in set(x)}
将输出一个计数:
{2: 2, 3: 4, 4: 2, 5: 2, 10: 2, 11: 3, 16: 2}
和索引:
{2: [1, 5],
3: [2, 4, 9, 14],
4: [11, 16],
5: [3, 12],
10: [7, 8],
11: [0, 10, 15],
16: [6, 13]}
如果您对最快的执行感兴趣,那么您会事先知道要查找的值,并且您的数组是一维的,否则您对展平数组上的结果感兴趣(在这种情况下,函数的输入应是np.flatten(arr)
不是只arr
),然后Numba是你的朋友:
import numba as nb
@nb.jit
def count_nb(arr, value):
result = 0
for x in arr:
if x == value:
result += 1
return result
或者,对于超大型阵列,并行化可能会有所帮助:
@nb.jit(parallel=True)
def count_nbp(arr, value):
result = 0
for i in nb.prange(arr.size):
if arr[i] == value:
result += 1
return result
对这些基准进行基准测试np.count_nonzero()
(也存在创建可以避免的临时数组的问题)和np.unique()
基于-的解决方案
import numpy as np
def count_np(arr, value):
return np.count_nonzero(arr == value)
import numpy as np
def count_np2(arr, value):
uniques, counts = np.unique(a, return_counts=True)
counter = dict(zip(uniques, counts))
return counter[value] if value in counter else 0
用于使用以下命令生成的输入:
def gen_input(n, a=0, b=100):
return np.random.randint(a, b, n)
获得以下图(图的第二行是对更快方法的放大):
表明基于Numba的解决方案比NumPy的解决方案明显更快,并且对于非常大的输入,并行方法比朴素的方法要快。
完整的代码在这里。
如果使用生成器处理非常大的数组,则可以选择。令人高兴的是,这种方法对数组和列表都适用,并且您不需要任何其他程序包。此外,您没有使用太多的内存。
my_array = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
sum(1 for val in my_array if val==0)
Out: 8