如何计算Python中ndarray中某些项的出现次数?

mfl*_*www 308 python numpy count multidimensional-array

在Python中,我有一个y 打印为的ndarrayarray([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])

我正在计算这个数组中有多少0s和多少1s.

但是,当我输入y.count(0)或者y.count(1),它说

numpy.ndarray 对象没有属性 count

我该怎么办?

ozg*_*gur 494

>>> 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}
Run Code Online (Sandbox Code Playgroud)

非笨拙的方式:

使用collections.Counter;

>> 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})
Run Code Online (Sandbox Code Playgroud)

  • 如果你想要字典,`dict(zip(*numpy.unique(a,return_counts = True))) (23认同)
  • 尝试对非常大的阵列(~30Gb)使用这两种方法。Numpy 方法内存不足,而“collections.Counter”工作得很好 (4认同)
  • 那将是```unique,count = numpy.unique(a,return_counts = True)dict(zip(unique,counts))``` (3认同)
  • 这是一个黑客。Numpy 有这个叫做 bincount() 或 histogram() 的函数 (3认同)
  • 如果我想访问数组中每个唯一元素的出现次数而不分配变量 - 计数,该怎么办?有什么提示吗? (2认同)
  • 对于那些想知道的人,这个答案适用于任何类型的 np 数组(例如,它适用于浮点数),与提供的一些答案不同。 (2认同)

Azi*_*lto 208

怎么样使用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
Run Code Online (Sandbox Code Playgroud)

  • 这个答案似乎比最赞成的人更好. (14认同)
  • @LYu - 在这个答案中,y是一个np.ndarray.此外 - 大多数(如果不是全部)np.something函数在没有问题的情况下在ndarrays上工作. (4认同)
  • 我认为这不适用于 OP 最初要求的“numpy.ndarray”。 (3认同)

小智 114

就个人而言,我会选择: (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()
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是最容易阅读的。问题是哪个速度最快且最节省空间 (2认同)

Aka*_*all 32

对于您的情况,您还可以查看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
Run Code Online (Sandbox Code Playgroud)

  • 这段代码可能是我试验过的大型数组最快的解决方案之一。将结果作为列表也是一个好处。谢谢! (3认同)
  • 并不是说numpy.bincount仅适用于整数。 (2认同)

Mil*_*are 19

将您的数组转换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 
Run Code Online (Sandbox Code Playgroud)


Joe*_*oel 16

y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
Run Code Online (Sandbox Code Playgroud)

如果你知道他们只是01:

np.sum(y)
Run Code Online (Sandbox Code Playgroud)

给你一些数量. np.sum(1-y)给出零.

为了略微一般性,如果你想计数0而不是零(但可能是2或3):

np.count_nonzero(y)
Run Code Online (Sandbox Code Playgroud)

给出非零数.

但如果你需要更复杂的东西,我认为numpy不会提供一个不错的count选择.在这种情况下,去集合:

import collections
collections.Counter(y)
> Counter({0: 8, 1: 4})
Run Code Online (Sandbox Code Playgroud)

这表现得像一个字典

collections.Counter(y)[0]
> 8
Run Code Online (Sandbox Code Playgroud)


Can*_*lan 13

如果您确切知道要查找的号码,可以使用以下内容;

lst = np.array([1,1,2,3,3,6,6,6,3,2,1])
(lst == 2).sum()
Run Code Online (Sandbox Code Playgroud)

返回数组中出现2的次数.


nor*_*ok2 11

如果您对最快的执行感兴趣,您提前知道要查找哪个值,并且您的数组是一维的,或者您对展平数组的结果感兴趣(在这种情况下,函数的输入应该benp.ravel(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
Run Code Online (Sandbox Code Playgroud)

或者,对于非常大的数组,并行化可能是有益的:

@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
Run Code Online (Sandbox Code Playgroud)

这些可以针对np.count_nonzero()(这也存在创建临时数组的问题 - 这在 Numba 解决方案中避免的问题)和np.unique()基于 的解决方案(实际上与其他解决方案相反地计算所有唯一值)进行基准测试。

import numpy as np


def count_np(arr, value):
    return np.count_nonzero(arr == value)
Run Code Online (Sandbox Code Playgroud)
import numpy as np


def count_np_uniq(arr, value):
    uniques, counts = np.unique(a, return_counts=True)
    counter = dict(zip(uniques, counts))
    return counter[value] if value in counter else 0 
Run Code Online (Sandbox Code Playgroud)

由于 Numba 支持“类型化”字典,因此还可以有一个函数来计算所有元素的所有出现次数。这更直接地竞争,np.unique()因为它能够在一次运行中计算所有值。这里提出了一个版本,它最终只返回单个值的元素数量(出于比较目的,与 中所做的类似count_np_uniq()):

@nb.jit
def count_nb_dict(arr, value):
    counter = {arr[0]: 1}
    for x in arr:
        if x not in counter:
            counter[x] = 1
        else:
            counter[x] += 1
    return counter[value] if value in counter else 0
Run Code Online (Sandbox Code Playgroud)

输入是通过以下方式生成的:

def gen_input(n, a=0, b=100):
    return np.random.randint(a, b, n)
Run Code Online (Sandbox Code Playgroud)

下图中报告了时间(第二行图是更快方法的放大图):

bm_full bm_zoom

表明基于 Numba 的简单解决方案对于较小的输入来说速度最快,而并行版本对于较大的输入速度最快。他们的 NumPy 版本在所有规模上都相当快。

当想要计算数组中的所有值时,np.unique()对于足够大的数组,比使用 Numba 手动实现的解决方案性能更高。

编辑:似乎 NumPy 解决方案在最近的版本中变得更快。在之前的迭代中,简单的 Numba 解决方案对于任何输入大小都优于 NumPy 的方法。


完整代码可在此处获取。


小智 6

我会使用 np.where:

how_many_0 = len(np.where(a==0.)[0])
how_many_1 = len(np.where(a==1.)[0])
Run Code Online (Sandbox Code Playgroud)


Ana*_*nas 6

怎么样len(y[y==0])len(y[y==1])


mic*_*ael 6

y.tolist().count(val)

使用val 0或1

由于python列表具有本机函数count,因此在使用该函数之前将其转换为list是一个简单的解决方案。


wor*_*ise 6

老实说,我发现转换为pandas Series或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()
Run Code Online (Sandbox Code Playgroud)

或者罗伯特·穆尔建议的这个漂亮的单线:

pd.Series([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]).value_counts()
Run Code Online (Sandbox Code Playgroud)

  • 只需注意:不需要DataFrame或numpy,可以直接从列表转到系列:`pd.Series([0,0,0,1,0,1,1,0,0,0,0 ,1]).value_counts()` (4认同)

Nær*_*een 6

没有人建议使用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
Run Code Online (Sandbox Code Playgroud)

numpy.unique(x, return_counts=True)和之间的疯狂加速numpy.bincount(x, minlength=np.max(x))

  • @Næreen `bincount` 仅适用于整数,因此它适用于OP的问题,但可能不适用于标题中描述的一般问题。您还尝试过将“bincount”与具有非常大整数的数组一起使用吗? (3认同)

Séb*_*ski 6

利用系列提供的方法:

>>> 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
Run Code Online (Sandbox Code Playgroud)


小智 5

另一个简单的解决方案可能是使用numpy.count_nonzero():

import numpy as np
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
y_nonzero_num = np.count_nonzero(y==1)
y_zero_num = np.count_nonzero(y==0)
y_nonzero_num
4
y_zero_num
8
Run Code Online (Sandbox Code Playgroud)

不要让这个名称误导你,如果你像布尔一样使用它,就像在例子中一样,它会做的伎俩.


kma*_*o23 5

要计算出现次数,您可以使用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
Run Code Online (Sandbox Code Playgroud)


jar*_*992 5

尝试这个:

a = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
list(a).count(1)
Run Code Online (Sandbox Code Playgroud)