Pythonでは、次のように出力y
されるndarray がありますarray([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
この配列にが0
いくつあるか、がいくつあるかを数えようとしています1
。
しかし、私は、入力したときy.count(0)
またはy.count(1)
それが言います、
numpy.ndarray
オブジェクトに属性がありませんcount
私は何をすべきか?
numpy.count_nonzero
です。
Pythonでは、次のように出力y
されるndarray がありますarray([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
この配列にが0
いくつあるか、がいくつあるかを数えようとしています1
。
しかし、私は、入力したときy.count(0)
またはy.count(1)
それが言います、
numpy.ndarray
オブジェクトに属性がありませんcount
私は何をすべきか?
numpy.count_nonzero
です。
回答:
>>> 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}
非派手な方法:
を使用し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})
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 = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
あなたは彼らがちょうどあることを知っている場合0
と1
:
np.sum(y)
1の数を与えます。 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
正直なところ、パンダシリーズまたは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
申し訳ありませんが、私が提案する3つのアプローチを機能と比較しても意味がありません。
bincount
ただし、@Næreen は整数に対してのみ機能するため、OPの問題に対しては機能しますが、タイトルに記載されている一般的な問題に対しては機能しない可能性があります。またbincount
、非常に大きなint を持つ配列を使用してみましたか?
bincount
は、の約4倍高速です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が複数の次元にあり、値の分布の発生を数えたい場合(=以下のパターン)
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
これは次の方法で簡単に行うことができます
y = np.array([0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1])
y.tolist().count(1)
一般的なエントリの場合:
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]}
最速の実行に関心がある場合、検索する値が事前にわかっており、配列が1Dであるか、それ以外の場合は、フラット化された配列の結果に関心があります(この場合、関数の入力はこと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)
次のプロットが得られます(プロットの2行目は、より高速なアプローチのズームです)。
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
Numpyにはこのためのモジュールがあります。ほんの小さなハック。入力配列をビンとして配置します。
numpy.histogram(y, bins=y)
出力は2つの配列です。1つは値自体、もう1つは対応する頻度です。
using numpy.count
$ a = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]
$ np.count(a, 1)