Как подсчитать появление определенного элемента в ndarray в Python?

в Python, у меня есть ndarray y это напечатано как array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])

Я пытаюсь сосчитать, сколько 0s и сколько 1s есть в этом массиве.

но когда я типа y.count(0) или y.count(1), он скажет

20 ответов


>>> 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}

Non-numpy way:

использовать 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})

Как насчет использования 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

лично я бы пошел на: (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()

для вашего случая вы также можете заглянуть в и 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 обеспечит хороший . В этом случае, перейдите к сборники:

import collections
collections.Counter(y)
> Counter({0: 8, 1: 4})

этот ведет себя, как дикт

collections.Counter(y)[0]
> 8

Если вы точно знаете, какой номер вы ищете, вы можете использовать следующее:

lst = np.array([1,1,2,3,3,6,6,6,3,2,1])
(lst == 2).sum()

возвращает, сколько раз 2 происходит в вашем массиве.


насчет len(y[y==0]) и len(y[y==1]) ?


еще одним простым решением может быть использование и 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

Не позволяйте имени вводить вас в заблуждение, если вы используете его с булевым, как в примере, это сделает трюк.


честно говоря, мне проще всего конвертировать в серию pandas или фрейм данных:

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()

или этот сценарий предложен Робертом Муил:

pd.Series([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]).value_counts()

Я бы использовал np.где:

how_many_0 = len(np.where(a==0.)[0])
how_many_1 = len(np.where(a==1.)[0])

y.tolist().count(val)

С val 0 или 1

поскольку список python имеет собственную функцию count переводим в списке перед использованием этой функции является простым решением.


чтобы подсчитать количество вхождений, вы можете использовать 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

никто не предложил использовать 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.size(x)) !


Это включает в себя еще один шаг, но более гибкое решение, которое также будет работать для 2d-массивов и более сложных фильтров, - создать булеву маску, а затем использовать .sum () на маске.

>>>>y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
>>>>mask = y == 0
>>>>mask.sum()
8

Это можно сделать легко в следующем методе

y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
y.tolist().count(1)

общий и простой ответ будет такой:

numpy.sum(MyArray==x)   # sum of a binary list of the occurence of x (=0 or 1) in MyArray

что привело бы к этому полному коду, как exemple

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

Так как ваш ndarray содержит только 0 и 1, вы можете использовать sum () для получения вхождения 1s и len () - sum (), чтобы получить вхождение 0s.

num_of_ones = sum(array)
num_of_zeros = len(array)-sum(array)

Если вы не хотите использовать numpy или модуль коллекции вы можете использовать словарь:

d = dict()
a = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]
for item in a:
    try:
        d[item]+=1
    except KeyError:
        d[item]=1

результат:

>>>d
{0: 8, 1: 4}

конечно, вы также можете использовать оператор if/else. Я думаю, что функция счетчика делает почти то же самое, но это более прозрачным.


Numpy имеет модуль для этого. Просто небольшой взлом. Поместите входной массив в качестве бункеров.

numpy.histogram(y, bins=y)

выход 2 массивов. Один с самими значениями, другой с соответствующими частотами.