numpy.bincount()で配列の非負整数をカウント

`numpy.bincount()`関数で一次元配列の中で非負整数が何回登場したかを整数ごとにカウントできる。オプション引数`weights`、`minlenghth`についても触れる。
```python 
import numpy as np
x = np.tile([0, 1], 3)
print(x)
# 実行結果　
# [0 1 0 1 0 1] 

print(np.bincount(x))
# 実行結果
# [3 3]

y = np.array([1, 2])
z = np.hstack((x,y))
print(z)
# 実行結果 
# [0 1 0 1 0 1 1 2]
 
print(np.bincount(z))
# 実行結果 
# [3 4 1]

# 値が連続していない場合　
a = np.array([1, 5, 5])
print(np.bincount(a))
# 実行結果　
# [0 1 0 0 0 2]
```
配列aの`np.amax(a)`の返り値がnだったとすると`np.bincount(a)`の返り値の配列の長さは0を含めてデフォルトでn+1になる。配列に含まれていない数字に関しては0が返される。  
一次元配列じゃない配列を入れると`ValueError`が出る。
```python
b = np.arange(6).reshape(2, 3)
try:
    np.bincount(b)
except ValueError as e:
    print("ValueError :", e)
# 実行結果　
# ValueError : object too deep for desired array
```
その場合一旦平坦化する 
```python 
print(np.bincount(b.ravel()))
# 実行結果 
# [1 1 1 1 1 1]
```



負の整数が入ってると`ValueError`が出る 
```python 
c = np.array([-2, 3, 10, 4, 8])
 
try:
    np.bincount(c)
except ValueError as e:
    print("ValueError :", e)
# 実行結果 
# ValueError : 'list' argument must have no negative elements
```
代替案的な何か 
```python 
d = np.vstack((np.arange(c.min(), c.max() + 1),
               np.bincount(c - c.min())))
print(d)
# 実行結果
# [[-2 -1  0  1  2  3  4  5  6  7  8  9 10]
#  [ 1  0  0  0  0  1  1  0  0  0  1  0  1]]
```





# オプション引数

`np.bincount(x, weights=None, minlength=0)`
```python 
z = np.array([0, 1, 0, 1, 0, 1, 1, 2])
w = np.array([.1, .3, -.4, .2, .6, 1.3, 3., -2.])
print(np.bincount(z, w))
# 実行結果　 
# [ 0.3 4.8 -2. ]
```
これは次と一緒　
```python 
print(np.array([w[z == i].sum() for i in np.unique(z)])
# 実行結果　
# [ 0.3 4.8 -2. ] 
```
`weights`はxと同じ形の必要がある。 
デフォルトでは`np.bincount(arr)`の返り値の長さは`np.amax(arr) + 1`になるが、オプション引数`minlength`で変更できる。
```python 
print(np.bincount(z))
# 実行結果 
# [3 4 1]

print(np.bincount(z, minlength=5)
# 実行結果 
# [3 4 1 0 0] 

print(np.bincount(z, minlength=1)
# 実行結果 
# [3 4 1] 
```
`minlength`が`np.amax(arr) + 1`よりも大きい場合は`np.bincount`の返り値の長さは`minlength`になる。　　
`minlenght`が`np.amax(arr) + 1`以下である場合、返り値の長さは`np.amax(arr) + 1`になる。　

# サンプルコード　
scikit-learnのirisデータセットに`np.bincount`を使ってみる。　
```python 
from sklearn.datasets import load_iris
iris = load_iris()
```
irisデータセットはクラス分類のためのトイデータ  
`iris.data`には150サンプルの４つの特徴量がnumpy_ndarrayとして格納されている。  
`iris.target`にはクラスラベル（３種類、1、2、3）
`iris.target_names`はクラスの名前
`iris.feature_names`に四つの特徴量の名前が入っている　
```python 
print(iris.data.shape)
# 実行結果 
# (150, 4) 

print(iris.target.shape)
# 実行結果 
# (150,)
 
print(np.unique(iris.target))
# 実行結果 
# [0 1 2]

print(iris.target_names)
# 実行結果 
# ['setosa' 'versicolor' 'virginica']

print(iris.feature_names)
# 実行結果
# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
```
では本題　
`np.bincount()`を使ってみる　
```python 
# 各クラスにサンプルが何個ずつあるか？
for target, count in zip(iris.target_names,
                         np.bincount(iris.target)):
    print(target, count)
# 実行結果
# setosa 50
# versicolor 50
# virginica 50

# sepal length (cm) の各クラスごとの平均　
sl = iris.data[:, 0]
averages = np.bincount(iris.target, sl) / np.bincount(iris.target)
for name, average in zip(iris.target_names, averages):
    print(name, "{:.2f}".format(average))
# 実行結果　
# setosa 5.01 
# versicolor 5.94
# virginica 6.59
```
# まとめ　
お疲れ様です 
バージョンは　
```python 
print(np.__version__)
# 実行結果 
# 1.21.5

import sklearn
print(sklearn.__version__)
# 実行結果 
# 1.0.2
```