NumPy配列ndarrayの条件を満たす要素数をカウント
NumPy配列ndarrayの条件を満たす要素数をカウントする方法について説明する。
条件を満たす要素数ではなく、配列のサイズ(全要素数)はsize属性で取得できる。
条件を満たす要素・行・列の抽出や削除、置換については以下の記事を参照。
本記事のサンプルコードのNumPyのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。
import numpy as np
print(np.__version__)
# 1.26.1
ndarrayの条件を満たす要素数をカウント: np.count_nonzero()
np.count_nonzero()は配列ndarrayの0でない要素の個数をカウントして返す。
a = np.arange(12).reshape((3, 4))
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(np.count_nonzero(a))
# 11
ndarrayをスカラー値と比較すると、bool値(True, False)を要素とするndarrayが返される。<や==, !=などで比較できる。
print(a < 4)
# [[ True True True True]
# [False False False False]
# [False False False False]]
print(a % 2 == 0)
# [[ True False True False]
# [ True False True False]
# [ True False True False]]
Trueは1, Falseは0とみなされるので、これらのndarrayをnp.count_nonzero()に渡すと、Trueの数、すなわち、条件を満たす要素の個数が得られる。
print(np.count_nonzero(a < 4))
# 4
print(np.count_nonzero(a % 2 == 0))
# 6
np.sum()でも同じ結果となるが、np.count_nonzero()のほうが高速。
print(np.sum(a < 4))
# 4
print(np.sum(a % 2 == 0))
# 6
ndarrayの行・列ごとに条件を満たす要素数をカウント
多次元配列に対するnp.count_nonzero()は、第二引数axisを指定することで各軸(各次元)に対する処理となる。デフォルトはaxis=Noneで、ndarray全体に対する処理。
二次元配列の場合、axis=0で列ごと、axis=1で行ごとの処理となる。行・列ごとに条件を満たす要素数をカウントできる。
a = np.arange(12).reshape((3, 4))
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(np.count_nonzero(a < 4))
# 4
print(np.count_nonzero(a < 4, axis=0))
# [1 1 1 1]
print(np.count_nonzero(a < 4, axis=1))
# [4 0 0]
引数keepdimsをTrueとすると、結果も元のndarrayと同じ次元数となる。
print(np.count_nonzero(a < 4, keepdims=True))
# [[4]]
print(np.count_nonzero(a < 4, axis=0, keepdims=True))
# [[1 1 1 1]]
print(np.count_nonzero(a < 4, axis=1, keepdims=True))
# [[4]
# [0]
# [0]]
なお、np.count_nonzero()の引数axisはバージョン1.12、引数keepdimsはバージョン1.19で追加された。np.sum()ではどちらもバージョン1.7で追加されたので、古いバージョンではnp.sum()を使えばよい。
np.any()で条件を満たす要素が一つでもあるか確認(全体、行・列ごと)
np.any()は、第一引数のndarrayにTrueの要素が一つでもあるときにTrueを返し、そうでないときはFalseを返す。
ndarrayに条件を満たす要素が一つでもあるかを確認できる。
a = np.arange(12).reshape((3, 4))
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(np.any(a < 4))
# True
print(np.any(a > 100))
# False
np.any()もnp.count_nonzero()と同じように、第二引数axisを指定すると行・列ごとの処理となる。
print(np.any(a < 4, axis=0))
# [ True True True True]
print(np.any(a < 4, axis=1))
# [ True False False]
例は省略するが、引数keepdimsも指定可能。
np.all()ですべての要素が条件を満たすか確認(全体、行・列ごと)
np.all()は、第一引数のndarrayの要素がすべてTrueのときにTrueを返し、そうでないときはFalseを返す。
ndarrayのすべての要素が条件を満たすかを確認できる。
a = np.arange(12).reshape((3, 4))
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(np.all(a < 4))
# False
print(np.all(a < 100))
# True
np.all()もnp.count_nonzero()と同じように、第二引数axisを指定すると行・列ごとの処理となる。
print(np.all(a < 4, axis=0))
# [False False False False]
print(np.all(a < 4, axis=1))
# [ True False False]
例は省略するが、引数keepdimsも指定可能。
複数条件を適用
複数の条件を組み合わせたい場合は、各条件式を括弧()で囲んで&(AND)や|(OR)でつなぐ。否定~(NOT)も使用可能。
a = np.arange(12).reshape((3, 4))
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print((a < 4) | (a % 2 == 0))
# [[ True True True True]
# [ True False True False]
# [ True False True False]]
print(np.count_nonzero((a < 4) | (a % 2 == 0)))
# 8
print(np.count_nonzero((a < 4) | (a % 2 == 0), axis=0))
# [3 1 3 1]
print(np.count_nonzero((a < 4) | (a % 2 == 0), axis=1))
# [4 2 2]
&, |ではなくand, orを使ったり、括弧を省略したりするとエラーになるので注意。
欠損値NaNをカウント
例えば、以下のようなデータが欠落したCSVファイルをndarrayとして読み込むと欠損値NaNが発生する。
a_nan = np.genfromtxt('data/src/sample_nan.csv', delimiter=',')
print(a_nan)
# [[11. 12. nan 14.]
# [21. nan nan 24.]
# [31. 32. 33. 34.]]
欠損値NaN同士は==で比較してもFalseになってしまうため、欠損値をカウントするにはnp.isnan()を使う。
print(np.nan == np.nan)
# False
print(a_nan == np.nan)
# [[False False False False]
# [False False False False]
# [False False False False]]
print(np.isnan(a_nan))
# [[False False True False]
# [False True True False]
# [False False False False]]
あとはこれまでの例と同じ。np.count_nonzero()やnp.sum()でTrueの数をカウントすればよい。
print(np.count_nonzero(np.isnan(a_nan)))
# 3
print(np.count_nonzero(np.isnan(a_nan), axis=0))
# [0 1 2 0]
print(np.count_nonzero(np.isnan(a_nan), axis=1))
# [1 2 0]
欠損値ではない要素をカウントしたい場合は否定~を使う。
print(~np.isnan(a_nan))
# [[ True True False True]
# [ True False False True]
# [ True True True True]]
欠損値の置換や削除については以下の記事を参照。
無限大infをカウント
要素が無限大infかどうかを判定する関数はnp.isinf()。正負どちらの無限大もTrueとなる。
a_inf = np.array([-np.inf, 0, np.inf])
print(a_inf)
# [-inf 0. inf]
print(np.isinf(a_inf))
# [ True False True]
正の無限大に対してTrueを返すnp.isposinf()、負の無限大に対してTrueを返すnp.isneginf()もある。
print(np.isposinf(a_inf))
# [False False True]
print(np.isneginf(a_inf))
# [ True False False]
無限大は==で比較できるので、正負どちらかのみを判定したい場合は==を使ってもよい。
print(a_inf == np.inf)
# [False False True]
print(a_inf == -np.inf)
# [ True False False]
あとはこれまでの例と同じ。
print(np.count_nonzero(np.isinf(a_inf)))
# 2
print(np.count_nonzero(np.isposinf(a_inf)))
# 1
print(np.count_nonzero(np.isneginf(a_inf)))
# 1
無限大の演算などについては以下の記事を参照。