NumPyで条件に合う要素・行・列を削除する方法|ブールインデックスとnp.deleteの使い分け

NumPy配列から条件に合う要素を削除するには、「残したい要素の条件」でブールインデックスを使って a[~(条件)] のように取り出すのが基本です。np.delete() を使う場合は、NumPy 1.19以降なら条件の真偽値配列をそのまま削除対象として渡せますが、2次元配列では axis を必ず指定します。

この記事では、条件による抽出と削除を「要素」「行」「列」に分けて、実行結果つきで整理します。インデックスを指定して削除する np.delete() の基本はnp.deleteの使い方|NumPyの配列から要素・行・列を削除する方法で詳しく扱っているので、ここでは「条件で選んで消す」場面に絞ります。コードはPython 3.12、NumPy 2.5.4で実行しました(2026年10月15日確認)。

早見表:やりたいこと別の書き方

やりたいこと 書き方 結果
条件に合う要素を取り出す a[a > 0] 1次元配列
条件に合う要素を削除する a[~(a > 0)] または np.delete(a, a > 0) 1次元配列
特定の値を削除する a[~np.isin(a, [8, 20])] 1次元配列
条件に合う行を削除する a[~(a[:, 0] >= 50)] または np.delete(a, mask, axis=0) 2次元のまま
負の値を1つでも含む行を削除する a[~(a < 0).any(axis=1)] 2次元のまま
条件に合う列だけ残す a[:, a[0] >= 10] 2次元のまま
形を変えずに条件外を置き換える np.where(a > 5, a, 0) 元と同じ形

条件で要素を抽出・削除する(1次元配列)

ブールインデックスの基本

a > 0 のような比較は、要素ごとに True / False が入った配列(ブール配列、マスク)を返します。これを角かっこに入れると True の位置の要素だけが取り出されます。~ でマスクを反転させると、条件に合う要素を「削除」した配列になります。

import numpy as np

a = np.array([10, -5, 20, -15, 30])
mask = a > 0
print(mask)
print(a[mask])
print(a[~mask])
[ True False  True False  True]
[10 20 30]
[ -5 -15]

複数の条件を組み合わせる

複数の条件は &(かつ)と |(または)でつなぎます。Pythonの and / or は使えず、各条件をかっこで囲む必要があります。特定の値をまとめて消したいときは np.isin() が便利です。

import numpy as np

a = np.array([3, 8, 12, 5, 20, 7])
print(a[(a >= 5) & (a <= 12)])
print(a[(a < 5) | (a > 12)])
print(a[np.isin(a, [8, 20])])
print(a[~np.isin(a, [8, 20])])
[ 8 12  5  7]
[ 3 20]
[ 8 20]
[ 3 12  5  7]

かっこを付けずに a >= 5 & a <= 12 と書くと、演算子の優先順位により 5 & a が先に計算され、さらに比較の連結として解釈されるため、「ValueError: The truth value of an array with more than one element is ambiguous.」というエラーになります。

np.delete() に条件を渡す

np.delete() は「削除する位置」を受け取る関数です。NumPyの公式ドキュメントによると、NumPy 1.19.0から、真偽値の配列は削除する要素のマスクとして扱われるようになりました(それ以前は0と1の整数として扱われていました)。位置の配列が必要なら np.where(条件)[0] で求められます。

import numpy as np

a = np.array([3, 8, 12, 5, 20, 7])
idx = np.where(a > 10)[0]
print(idx)
print(np.delete(a, idx))
print(np.delete(a, a > 10))
print(a)
[2 4]
[3 8 5 7]
[3 8 5 7]
[ 3  8 12  5 20  7]

最後の行のとおり、np.delete() は元の配列を変更せず、削除後の新しい配列を返します。結果を使うには a = np.delete(a, ...) のように代入し直してください。公式ドキュメントでも、多くの場合はブールマスクを使う方が望ましい(マスクを再利用できる)と説明されています。

2次元配列で条件に合う要素を扱う

2次元配列にブールインデックスを使うと、結果は1次元配列になります。行と列の形を保ったまま条件に合わない値だけを置き換えたいなら np.where(条件, 元の値, 置き換える値) を使います。

import numpy as np

a = np.array([[10, 20, 30],
              [4, 5, 6],
              [70, 80, 90]])

print(a[a > 5])
print(np.where(a > 5, a, 0))
[10 20 30  6 70 80 90]
[[10 20 30]
 [ 0  0  6]
 [70 80 90]]

2次元配列の「要素だけ」を消すと、行ごとの要素数がそろわなくなるため、2次元の形は保てません。形を保ちたいなら、行単位・列単位で消すか、np.where() で置き換えるかのどちらかになります。

条件で行を抽出・削除する

ある列の値で行を選ぶ

1列目(インデックス0)の値が50以上の行を削除します。a[:, 0] >= 50 は行の数と同じ長さのブール配列になるので、そのまま行の選択に使えます。

import numpy as np

a = np.array([[10, 20, 30],
              [4, 5, 6],
              [70, 80, 90]])

keep = a[:, 0] < 50
print(a[keep])
print(a[~keep])
print(np.delete(a, np.where(~keep)[0], axis=0))
[[10 20 30]
 [ 4  5  6]]
[[70 80 90]]
[[10 20 30]
 [ 4  5  6]]

np.delete() で行を消すときは axis を忘れない

np.delete() に axis を指定しないと、配列は1次元に平らにされてから削除されます。真偽値のマスクを渡した場合は、長さが合わずにエラーになります。

import numpy as np

a = np.array([[10, 20, 30],
              [4, 5, 6],
              [70, 80, 90]])

drop = a[:, 0] >= 50
print(np.delete(a, drop, axis=0))
print(np.delete(a, np.where(drop)[0]))
try:
    np.delete(a, drop)
except ValueError as e:
    print("ValueError:", e)
[[10 20 30]
 [ 4  5  6]]
[10 20  4  5  6 70 80 90]
ValueError: boolean array argument obj to delete must be one dimensional and match the axis length of 9

2行目は「行2を消したつもり」が、平らにした配列の2番目の要素(30)を消しただけになっています。エラーにならないぶん気づきにくいので注意してください。

どこか1つでも条件に合う行を削除する(any・all)

「負の値を1つでも含む行を消す」のように、行の中のどれかの要素で判定したいときは any(axis=1)、すべての要素で判定したいときは all(axis=1) を使います。

import numpy as np

a = np.array([[1, -2, 3],
              [4, 5, 6],
              [-7, 8, -9]])

print(a[(a < 0).any(axis=1)])
print(a[~(a < 0).any(axis=1)])
print(a[(a > 0).all(axis=1)])
[[ 1 -2  3]
 [-7  8 -9]]
[[4 5 6]]
[[4 5 6]]

NaN(欠損値)を含む行を消す場合も同じ考え方で、a[~np.isnan(a).any(axis=1)] と書けます。

import numpy as np

a = np.array([[1.0, np.nan, 3.0],
              [4.0, 5.0, 6.0],
              [np.nan, 8.0, 9.0]])

print(a[~np.isnan(a).any(axis=1)])
print(a[~np.isnan(a)])
[[4. 5. 6.]]
[1. 3. 4. 5. 6. 8. 9.]

NaNの扱いはNumPyでNaNを含む行・列を削除する方法で詳しく解説しています。

条件で列を抽出・削除する

列を選ぶときは、列の数と同じ長さのブール配列を a[:, マスク] の位置に入れます。1行目の値で判定する例と、列ごとの合計で判定する例です。

import numpy as np

a = np.array([[1, 10, 100],
              [2, 20, 200],
              [3, 30, 300]])

cols = a[0] >= 10
print(cols)
print(a[:, cols])
print(a[:, a.sum(axis=0) < 100])
[False  True  True]
[[ 10 100]
 [ 20 200]
 [ 30 300]]
[[ 1 10]
 [ 2 20]
 [ 3 30]]

行のときは axis=1(行の中を横に見る)、列のときは axis=0(列の中を縦に見る)で集計する、と覚えると混乱しにくくなります。

削除と書き換えの注意点

ブールインデックスで取り出した配列はコピーなので、書き換えても元の配列には影響しません。元の配列の中で条件に合う要素を書き換えたいときは、a[条件] = 値 の形で代入します。

import numpy as np

a = np.array([5, 1, 4, 1, 3])
b = a[a != 1]
b[0] = 100
print(a, b)

c = a.copy()
c = 0
print(c)
[5 1 4 1 3] [100   4   3]
[5 0 4 0 3]

そのほかの関数:np.extract・np.compress・np.flatnonzero

同じことを関数の形で書くこともできます。np.flatnonzero() は条件に合う位置(平らにしたときのインデックス)を返すので、np.delete() に渡す位置を作るときにも使えます。

import numpy as np

a = np.arange(1, 11)
print(np.extract(a % 3 == 0, a))
print(np.compress(a % 3 == 0, a))
print(np.flatnonzero(a % 3 == 0))
[3 6 9]
[3 6 9]
[2 5 8]

条件に合う要素の数だけを知りたいときはnp.count_nonzeroの使い方を参照してください。

Pythonのリストから削除する場合

「python 配列 削除」で調べていて、扱っているのがNumPy配列ではなくPythonのリストなら、書き方が変わります。条件で削除するならリスト内包表記、値で1つ消すなら remove()、位置で消すなら del や pop() です。

nums = [3, 8, 12, 5, 20, 7]
print([x for x in nums if x <= 10])

nums.remove(12)
print(nums)
del nums[0]
print(nums)
print(nums.pop(), nums)
[3, 8, 5, 7]
[3, 8, 5, 20, 7]
[8, 5, 20, 7]
7 [8, 5, 20]

リストの remove()・del・pop() は元のリストを直接変更しますが、NumPyの np.delete() やブールインデックスは新しい配列を返す、という違いがあります。リストとNumPy配列の違いはPythonのリスト・array・NumPy配列(ndarray)の違いで比較しています。

よくある質問

Q. NumPyで条件に合う要素を削除するにはどうすればよいですか?

a[~(a > 0)] のように、条件を反転したマスクで残したい要素を取り出すのが基本です。NumPy 1.19以降は np.delete(a, a > 0) のように真偽値の配列をそのまま渡しても削除できます。

Q. np.delete() を実行しても元の配列が変わらないのはなぜですか?

np.delete() は削除後の新しい配列を返し、元の配列はそのまま残す仕様だからです。a = np.delete(a, 位置) のように代入し直してください。

Q. 2次元配列で条件に合う行だけを削除するには?

行の数と同じ長さのブール配列を作り、a[~mask] とするか、np.delete(a, mask, axis=0) とします。axis を省略すると配列が1次元に平らにされるので注意してください。

Q. 2次元配列の形を保ったまま条件に合わない値を消せますか?

要素だけを消すと行ごとの要素数がそろわなくなるため、形は保てません。np.where(条件, a, 0) のように別の値に置き換えるか、行単位・列単位で削除してください。

NumPy|抽出・条件の関連記事

条件指定やスライスで、配列から必要な要素を取り出す操作の記事です。

NumPy全体の使い方は「NumPyの使い方」、「NumPy関数一覧」でまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら