numpy.bincount()
関数で一次元配列の中で非負整数が何回登場したかを整数ごとにカウントできる。オプション引数weights
、minlenghth
についても触れる。
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
が出る。
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
その場合一旦平坦化する
print(np.bincount(b.ravel()))
# 実行結果
# [1 1 1 1 1 1]
負の整数が入ってるとValueError
が出る
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
代替案的な何か
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)
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. ]
これは次と一緒
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
で変更できる。
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
を使ってみる。
from sklearn.datasets import load_iris
iris = load_iris()
irisデータセットはクラス分類のためのトイデータ
iris.data
には150サンプルの4つの特徴量がnumpy_ndarrayとして格納されている。
iris.target
にはクラスラベル(3種類、1、2、3)
iris.target_names
はクラスの名前
iris.feature_names
に四つの特徴量の名前が入っている
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()
を使ってみる
# 各クラスにサンプルが何個ずつあるか?
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
まとめ
お疲れ様です
バージョンは
print(np.__version__)
# 実行結果
# 1.21.5
import sklearn
print(sklearn.__version__)
# 実行結果
# 1.0.2