np.count_nonzeroの使い方|NumPyで条件に合う要素数・Trueの数を数える(axis・NaN・sumとの速度比較)
np.count_nonzero(a)は、配列のうち0でない要素(ブール配列ならTrue)の個数を返す関数です。条件に合う要素数はnp.count_nonzero(arr > 0)のように条件式を渡して数え、行ごと・列ごとに数えるときはaxisを指定します。
この記事のコードはすべてNumPy 2.5.4・Python 3.12で実行し、出力をそのまま載せています(2026年10月15日確認)。引数の仕様は公式リファレンスnumpy.count_nonzeroに沿っています。
np.count_nonzeroの書式と引数
numpy.count_nonzero(a, axis=None, *, keepdims=False)
| 引数 | 意味 | 既定値 |
|---|---|---|
a |
数える対象の配列(リストなども可) | 必須 |
axis |
数える方向。整数かタプル。指定しなければ全体を数える | None |
keepdims |
Trueにすると、数えた軸を長さ1の次元として残す |
False |
公式リファレンスでは、「0でない」とはブール値として評価したときに真になる値のことで、0以外の数と空でない文字列が含まれる、と説明されています。戻り値は、axisを指定しなければ整数1つ、指定すれば整数の配列です。
基本:0でない要素と、条件に合う要素を数える
import numpy as np
arr = np.array([10, -5, 0, 20, -15, 30, 0])
print(np.count_nonzero(arr)) # 0でない要素の数
print(np.count_nonzero(arr > 0)) # 0より大きい要素の数
print(arr > 0)
5
3
[ True False False True False True False]
arr > 0は要素ごとに比較したTrue/Falseの配列(ブール配列)を返します。Trueは「0でない値」として扱われるので、ブール配列をcount_nonzeroに渡すとTrueの数、つまり条件に合う要素数になります。「numpy count true」で探している場合も、答えはこの書き方です。
0の個数を数える(count_zeroはない)
NumPyにcount_zeroという関数はありません。0の個数は、全要素数から0でない要素数を引くか、== 0の条件を数えます。
print(arr.size - np.count_nonzero(arr))
print(np.count_nonzero(arr == 0))
2
2
複数の条件を組み合わせて数える
範囲指定(AND)は&、どちらか(OR)は|でつなぎます。Pythonのand/orは配列には使えず、各条件はかっこで囲む必要があります。
print(np.count_nonzero((arr >= 0) & (arr <= 20))) # 0以上20以下
print(np.count_nonzero((arr < 0) | (arr > 20))) # 0未満または20より大きい
4
3
2次元配列で行ごと・列ごとに数える(axis・keepdims)
4人×3科目の点数で、60点以上の数を数えてみます。
# 4人 × 3科目の点数
scores = np.array([[80, 45, 92],
[60, 70, 65],
[55, 88, 75],
[90, 20, 65]])
mask = scores >= 60
print(np.count_nonzero(mask)) # 全体
print(np.count_nonzero(mask, axis=0)) # 科目(列)ごと
print(np.count_nonzero(mask, axis=1)) # 人(行)ごと
print(np.count_nonzero(mask, axis=1, keepdims=True)) # 行ごと・次元を残す
9
[3 2 4]
[2 3 2 2]
[[2]
[3]
[2]
[2]]
| 指定 | 数える方向 | 結果の形 |
|---|---|---|
| なし | 全要素 | 整数1つ(9) |
axis=0 |
縦方向に数える=列ごと | (3,) |
axis=1 |
横方向に数える=行ごと | (4,) |
axis=1, keepdims=True |
行ごと | (4, 1) |
keepdims=Trueは、結果を元の配列と計算したいとき(例:行ごとの合格科目数で各セルを割る)に、ブロードキャストの形を合わせるために使います。keepdimsの考え方はNumPyのkeepdims=Trueとは?で詳しく説明しています。
NaN(欠損値)の数え方に注意
NaNは0ではないので、count_nonzeroにそのまま渡すと「0でない値」として数えられてしまいます。NaNの数を数えるときはnp.isnan()でブール配列にしてから渡します。
x = np.array([1.0, np.nan, 0.0, np.nan, 3.0])
print(np.count_nonzero(x)) # NaNも0でない値として数えられる
print(np.count_nonzero(np.isnan(x))) # NaNの数
print(np.count_nonzero(~np.isnan(x))) # NaNでない要素の数
4
2
3
NaNを含む行や列を取り除く方法はNumPyでNaNを含む行・列を削除する方法にまとめています。
文字列の配列にも使える
公式リファレンスのとおり、空でない文字列は「0でない値」として数えられます。
s = np.array(["a", "", "b", ""])
print(np.count_nonzero(s)) # 空文字でない要素の数
print(np.count_nonzero(s == "a")) # "a" の数
2
1
sum()・np.where()との違いと速度
ブール配列のTrueは1として足し算されるので、mask.sum()やnp.sum(mask)でも同じ数が得られます。np.where(mask)はTrueの位置(インデックス)を返すので、その長さでも数えられます。結果はどれも同じです。
r1 = np.count_nonzero(arr > 0)
r2 = (arr > 0).sum()
r3 = np.sum(arr > 0)
print(type(r1), type(r2), type(r3), r1, r2, r3)
print(np.where(arr > 0))
<class 'numpy.int64'> <class 'numpy.int64'> <class 'numpy.int64'> 3 3 3
(array([0, 3, 5]),)
1,000万要素のブール配列で、4つの書き方の実行時間をtimeitで測りました(各20回の平均を5回測った最小値)。
import timeit
import numpy as np
rng = np.random.default_rng(0)
a = rng.random(10_000_000)
mask = a > 0.5
for stmt in ["np.count_nonzero(mask)", "mask.sum()", "np.sum(mask)", "len(np.where(mask)[0])"]:
t = min(timeit.repeat(stmt, globals=globals(), number=20, repeat=5)) / 20
print(f"{stmt:24s} {t*1000:.2f} ms")
np.count_nonzero(mask) 0.33 ms
mask.sum() 1.95 ms
np.sum(mask) 1.94 ms
len(np.where(mask)[0]) 6.74 ms
筆者の環境(Apple M2、NumPy 2.5.4)ではcount_nonzeroがいちばん速く、sum()の約6分の1の時間でした。数値は環境によって変わりますが、np.where()は位置の配列を作るぶん遅くなります。個数だけが必要ならcount_nonzero、位置も使うならnp.where()、割合(平均)を出すならnp.mean(mask)、と使い分けます。
| 書き方 | 返すもの | 向いている場面 |
|---|---|---|
np.count_nonzero(mask) |
個数 | 個数だけ知りたい |
mask.sum() |
個数 | ほかの集計と書き方をそろえたい |
np.mean(mask) |
割合(0〜1) | 条件に合う割合を出したい |
np.where(mask) |
位置(インデックス) | どこにあるかも使いたい |
np.where()の使い方はnp.whereの使い方で解説しています。
値ごとの出現回数をまとめて数える
特定の1つの値ならnp.count_nonzero(v == 3)で数えられますが、すべての値の出現回数を一度に知りたいときはnp.unique(..., return_counts=True)が便利です。0以上の整数ならnp.bincount()も使えます。
v = np.array([3, 1, 3, 2, 3, 1])
print(np.count_nonzero(v == 3))
vals, counts = np.unique(v, return_counts=True)
print(vals, counts)
print(np.bincount(v)) # 0, 1, 2, 3 それぞれの個数
3
[1 2 3] [2 1 3]
[0 2 1 3]
np.uniqueの詳しい使い方はnp.uniqueとは?を参照してください。
よくある質問
Q. np.count_nonzeroとsum()はどちらを使えばよいですか。
結果は同じです。個数を数えるだけならcount_nonzeroのほうが意図が読み取りやすく、今回の計測でもsum()より速く動きました。行ごと・列ごとに数えるときは、どちらもaxisを指定できます。
Q. 0の個数を数える関数はありますか。
count_zeroという関数はありません。arr.size – np.count_nonzero(arr)、またはnp.count_nonzero(arr == 0)で数えます。
Q. NaNの数を数えたら多すぎる値が出ました。
NaNは0ではないため、count_nonzeroにそのまま渡すと数に入ります。NaNの数はnp.count_nonzero(np.isnan(x))で数えてください。
Q. pandasのDataFrameでも使えますか。
使えます。np.count_nonzero(df[“列”] > 0)のように条件式を渡せば個数が返ります。pandasだけで書くなら(df[“列”] > 0).sum()でも同じ結果になります。
まとめ
np.count_nonzero(a)は0でない要素(True)の個数を返す- 条件に合う要素数は
np.count_nonzero(条件式)。複数条件は&・|とかっこ - 行ごと・列ごとは
axis、形を残すならkeepdims=True - 0の個数は
sizeから引く。NaNはnp.isnan()を通してから数える - 個数だけなら
count_nonzero、割合はnp.mean、位置はnp.where
NumPy|抽出・条件の関連記事
条件指定やスライスで、配列から必要な要素を取り出す操作の記事です。



