파이썬에서 ndarray에서 특정 항목의 발생을 계산하는 방법은 무엇입니까?


376

파이썬에서는 다음 y 과 같이 인쇄 된 ndarray 가 있습니다.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])

이 배열에 01개와 몇 개가 있는지 계산하려고합니다 .

그러나 나는 입력 할 때 y.count(0)또는 y.count(1)그것이 말하는,

numpy.ndarray 객체에 속성이 없습니다 count

어떻게해야합니까?


8
에이스와 제로 만 있기 때문에 합과 길이 함수를 사용할 수 없습니까?
codingEnthusiast

이 경우 간단히을 사용하는 것도 가능합니다 numpy.count_nonzero.
Mong H. Ng

답변:


610
>>> 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 방법 :

사용 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})

3
```unique, counts = numpy.unique (a, return_counts = True) dict (zip (unique, counts))```
파쇄

25
사전을 원한다면dict(zip(*numpy.unique(a, return_counts=True)))
Seppo Enarvi

2
변수 개수에 할당하지 않고 배열의 각 고유 요소의 발생 횟수에 액세스하려면 어떻게해야합니까? 그것에 대한 힌트가 있습니까?
sajis997

@ sajis997과 같은 목표를 가지고 있습니다. 'count'를 그룹 단위로 집계 함수로 사용하고 싶습니다
p_sutherland

1
매우 큰 어레이 (~ 30Gb)에 대해 두 가지 방법을 모두 사용해 보았습니다. (가) 반면 NumPy와 방법은 메모리가 부족 collections.Counter잘 일
이반 Novikov 보낸을

252

무엇 사용에 대한 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

20
이 답변은 가장 많이 찬성 한 답변보다 낫습니다.
Alex

1
numpy.ndarrayOP가 원래 요청 한대로 작동하지 않을 것이라고 생각합니다 .
LYu

5
@LYu-y는이 답변의 np.ndarray입니다. 또한 대부분의 np.something 기능이 문제없이 ndarray에서 작동합니다.
mmagnuski

132

개인적으로, 나는 가고 싶어 : (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()

1
읽기 가장 쉬운 책입니다. 문제는 가장 빠르고 가장 효율적인 공간입니다.
Nathan

벡터를 평가하기 때문에 numpy.count_nonzero (y == 0)보다 공간 효율성이 떨어질 수 있습니다 (y == 0)
Sridhar Thiagarajan

나는 matlab / octave와 유사하기 때문에 이것을 좋아한다sum( vector==value )
ePi272314

39

귀하의 경우에는 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

이 코드는 내가 실험 한 더 큰 어레이를위한 가장 빠른 솔루션 중 하나 일 수 있습니다. 결과를 목록으로 얻는 것도 보너스입니다. 고맙습니다!
김영섭

'a'가 n 차원 배열이면 다음을 사용할 수 있습니다. np.bincount (np.reshape (a, a.size))
Ari

21

배열로 변환 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 

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

당신은 그들이 단지 것을 알고있는 경우 01:

np.sum(y)

당신에게 하나의 숫자를 제공합니다. np.sum(1-y)제로를 제공합니다.

약간의 일반성을 위해 00이 아닌 (그러나 2 또는 3) 계산 하지 않으려는 경우 :

np.count_nonzero(y)

0이 아닌 수를 제공합니다.

그러나 더 복잡한 것이 필요하다면 numpy가 좋은 count옵션 을 제공하지 않을 것이라고 생각 합니다. 이 경우 컬렉션으로 이동하십시오.

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

이것은 dict처럼 행동합니다

collections.Counter(y)[0]
> 8

13

원하는 번호를 정확히 알고 있다면 다음을 사용할 수 있습니다.

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

배열에서 2가 몇 번 발생했는지를 반환합니다.


8

솔직히 팬더 시리즈 또는 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()

4
참고 사항 : DataFrame 또는 numpy가 필요하지 않으며 목록에서 시리즈로 직접 이동할 수 있습니다. pd.Series([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]).value_counts()
Robert Muil

굉장히 좋은 라이너입니다. 크게
단어 :

8

아무도 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))!


히스토그램과 비교하면 어떻습니까?
john ktejik

@johnktejik np.histogram은 같은 것을 계산하지 않습니다. 내가 제안한 세 가지 접근법을 histogram기능 과 비교하는 것은 아무런 의미가 없습니다 .
Næreen

1
@ Næreen bincount은 정수에 대해서만 작동하므로 OP의 문제에는 작동하지만 제목에 설명 된 일반적인 문제에는 작동하지 않을 수 있습니다. 또한 bincount매우 큰 정수 를 가진 배열을 사용해 보셨습니까?
불멸의 밤

@ImperishableNight 아니오 큰 정수로 시도하지는 않았지만 누구나 그렇게하고 자신의 벤치 마크를 게시 할 수 있습니다 :-)
Næreen

이 평가 절하 트릭에 감사합니다! 내 컴퓨터에서 bincount보다 약 4 배 빠릅니다 unique.
Björn Lindqvist


6

y.tolist().count(val)

val 0 또는 1

파이썬 목록에는 기본 count함수가 있으므로 해당 함수를 사용하기 전에 목록으로 변환하는 것이 간단한 해결책입니다.


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

예와 같이 부울과 함께 이름을 사용하면 이름을 잘못 인도하지 마십시오.


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

4

np.where를 사용합니다.

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

3

시리즈가 제공하는 방법을 활용하십시오.

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

2

일반적이고 간단한 대답은 다음과 같습니다.

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가 여러 차원에 있고 선으로 값 분포가 발생하는 횟수를 계산하려는 경우 (이후 패턴)

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

2

사전 이해력을 사용하여 깔끔한 원 라이너를 만들 수 있습니다. 사전 이해에 대한 자세한 내용은 여기를 참조하십시오.

>>>counts = {int(value): list(y).count(value) for value in set(y)}
>>>print(counts)
{0: 8, 1: 4}

그러면 ndarray의 값을 키로 사용하고 값의 개수를 키 값으로 사용하는 사전을 만듭니다.

이 형식의 배열에서 값의 발생을 계산할 때마다 작동합니다.


2

이 시도:

a = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
list(a).count(1)

1

다음 방법으로 쉽게 수행 할 수 있습니다.

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

1

ndarray에 0과 1 만 포함되므로 sum ()을 사용하여 1의 발생을 얻고 len ()-sum ()을 사용하여 0의 발생을 얻을 수 있습니다.

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

1

여기에는 1과 0 만있는 특별한 배열이 있습니다. 트릭은

np.mean(x)

배열에서 1의 백분율을 제공합니다. 또는

np.sum(x)
np.sum(1-x)

배열에서 1과 0의 절대 숫자를 제공합니다.


1
dict(zip(*numpy.unique(y, return_counts=True)))

Seppo Enarvi의 의견을 여기에 복사했습니다.


0

여기에는 하나 이상의 단계가 포함되지만 2D 배열 및 더 복잡한 필터에도 사용할 수있는보다 유연한 솔루션은 부울 마스크를 만든 다음 마스크에서 .sum ()을 사용하는 것입니다.

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

0

numpy 또는 collections 모듈을 사용하지 않으려면 사전을 사용할 수 있습니다.

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 문을 사용할 수도 있습니다. 카운터 기능은 거의 똑같지 만 더 투명합니다.


0

일반 항목의 경우 :

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

0

여기에 특정 숫자의 발생 횟수를 계산할 수있는 코드가 있습니다. 코드에 따라

count_of_zero = list (y [y == 0]). count (0)

인쇄 (count_of_zero)

// 일치에 따라 부울 값이 있고 True 값에 따라 숫자 0이 반환됩니다.


0

가장 빠른 실행에 관심이 있다면 찾고자하는 값을 미리 알고 배열이 1D이거나 평평한 배열의 결과에 관심이있는 경우 (이 경우 함수의 입력은 ) np.flatten(arr)대신 arrNumba는 친구입니다.

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)

다음과 같은 도표를 얻습니다 (두 번째 줄의 도표는 빠른 접근 방식을 확대 한 것입니다).

bm_full bm_zoom

Numba 기반 솔루션이 NumPy 솔루션보다 눈에 띄게 빠르며, 매우 큰 입력의 경우 병렬 방식이 순진한 솔루션보다 빠릅니다.


전체 코드는 여기에 있습니다 .


0

발전기를 사용하여 매우 큰 배열을 처리하는 경우 옵션이 될 수 있습니다. 여기서 좋은 점은이 방법이 배열과 목록 모두에서 잘 작동하며 추가 패키지가 필요 없다는 것입니다. 또한 많은 메모리를 사용하고 있지 않습니다.

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

-1

Numpy에는이를위한 모듈이 있습니다. 작은 해킹. 입력 배열을 빈으로 넣습니다.

numpy.histogram(y, bins=y)

출력은 2 개의 배열입니다. 하나는 값 자체가 있고 다른 하나는 해당 주파수가 있습니다.


'빈'은 숫자가 아닌가?
john ktejik

1
네, @johnktejik이 맞습니다. 이 답변은 효과가 없습니다 .
Næreen

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.