この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:10:02

タイトル: 要素の削除
SEOタイトル: NumPy 要素削除完全ガイド(np.delete / Boolean Mask / axis 指定)

この記事の要点
  • NumPy 配列の要素削除は np.delete(arr, idx, axis=None) が基本
  • axis=0 で行削除、axis=1 で列削除、axis=None で flatten 後に削除
  • 複数削除: np.delete(arr, [1, 3, 5]) のようにインデックスのリスト指定
  • 条件削除は Boolean マスクが効率的: arr[arr > 5]arr[~(arr == 0)]
  • np.delete新規配列を返す(元配列は不変)→ メモリ効率を意識

np.delete の基本

NumPy 配列は「サイズ可変なリスト」ではないため、Python の list.pop() 相当の操作は新しい配列を生成する形で行います。中心 API は np.delete():

import numpy as np

a = np.array([10, 20, 30, 40, 50])

# インデックス 2 を削除 (30 が消える)
b = np.delete(a, 2)
print(b)   # [10 20 40 50]

# 元配列 a は変わらない
print(a)   # [10 20 30 40 50]

# 複数インデックス
c = np.delete(a, [0, 4])
print(c)   # [20 30 40]

# スライス指定(後ろ 2 つを削除)
d = np.delete(a, np.s_[-2:])
print(d)   # [10 20 30]

2 次元配列での行・列削除

m = np.arange(12).reshape(3, 4)
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11]])

# 行削除 (axis=0)
np.delete(m, 1, axis=0)
# array([[ 0,  1,  2,  3],
#        [ 8,  9, 10, 11]])

# 列削除 (axis=1)
np.delete(m, 1, axis=1)
# array([[ 0,  2,  3],
#        [ 4,  6,  7],
#        [ 8, 10, 11]])

# 複数列
np.delete(m, [0, 2], axis=1)
# array([[ 1,  3],
#        [ 5,  7],
#        [ 9, 11]])

# axis 省略 → flatten 後に削除
np.delete(m, [0, 5])
# array([ 1,  2,  3,  4,  6,  7,  8,  9, 10, 11])

条件削除: Boolean マスク

np.delete は「インデックス指定」ベース。「条件に合うものを除外」したいときはBoolean マスクを使う方が高速で読みやすいです。

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

# 5 より大きい要素のみ残す(= 5 以下を削除)
result = a[a > 5]
print(result)   # [ 6  7  8  9 10]

# 偶数だけ残す
print(a[a % 2 == 0])   # [ 2  4  6  8 10]

# 0 を削除
b = np.array([1, 0, 2, 0, 3, 0])
print(b[b != 0])       # [1 2 3]

# 複数条件 (&, | を使う、and/or は使えない)
print(a[(a > 2) & (a < 8)])   # [3 4 5 6 7]
print(a[(a < 3) | (a > 7)])   # [ 1  2  8  9 10]

# 反転 ~
mask = a > 5
print(a[~mask])   # [1 2 3 4 5]

np.where と組み合わせる

a = np.array([10, 20, 30, 40, 50])

# 条件にマッチするインデックスを取得
idx = np.where(a > 25)[0]
print(idx)   # [2 3 4]

# そのインデックスを削除(つまり 25 以下のみ残す)
result = np.delete(a, idx)
print(result)   # [10 20]

# == マスク方式と同じ結果
print(a[a <= 25])   # [10 20]  ← より直接的

NaN や特定値の除去

a = np.array([1.0, np.nan, 2.0, np.inf, 3.0, -np.inf])

# NaN 除去
a[~np.isnan(a)]       # [ 1.  2. inf  3. -inf]

# Inf / NaN 全て除去
a[np.isfinite(a)]     # [1. 2. 3.]

# 重複除去 (順序は維持されない)
b = np.array([3, 1, 4, 1, 5, 9, 2, 6, 5, 3])
np.unique(b)          # [1 2 3 4 5 6 9]

# 順序を保ったまま重複除去 (pandas 経由が簡単)
import pandas as pd
pd.Series(b).drop_duplicates().to_numpy()   # [3 1 4 5 9 2 6]

パフォーマンス比較

大きな配列では、Boolean マスクと np.delete の速度差は無視できません:

import numpy as np
import time

a = np.arange(10_000_000)

# 方法 A: np.delete
start = time.time()
b = np.delete(a, np.where(a % 2 == 0)[0])
print(f"np.delete: {time.time() - start:.3f}s")

# 方法 B: Boolean マスク
start = time.time()
c = a[a % 2 != 0]
print(f"mask    : {time.time() - start:.3f}s")

# ★ Boolean マスクの方が 5-10 倍速い
用途推奨 API備考
位置指定で 1〜数件削除np.delete(a, idx)読みやすい
大量削除・条件削除Boolean マスク a[cond]★ 高速
NaN / inf 除外a[np.isfinite(a)]専用関数
重複除去np.unique(a)ソートされる
行・列単位np.delete(m, i, axis=0/1)axis 必須

メモリ効率の注意(コピー vs ビュー)

import numpy as np

a = np.arange(10_000_000)

# np.delete は新規配列を返す(コピー) → 元と同サイズのメモリが必要
b = np.delete(a, 0)
print(b.base is None)   # True (独立した配列)

# スライス(ビュー)は元のメモリを共有
v = a[1:]
print(v.base is a)      # True (ビュー)

# ★ 大きな配列の頭・末尾削除はスライス推奨
head_drop = a[1:]       # 0 番目を「論理的に」削除
tail_drop = a[:-1]      # 末尾を「論理的に」削除

多次元での Boolean マスク

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

# 全要素対象(1 次元化される)
m[m > 5]   # array([6, 7, 8, 9])

# 行単位の条件(合計が 10 以下の行のみ残す)
m[m.sum(axis=1) <= 10]
# array([[1, 2, 3]])

# 列単位の条件
m[:, m.sum(axis=0) > 12]
# 列 2 (sum=18) のみ残す
# array([[3], [6], [9]])

Python list との違い

操作Python listNumPy ndarray
末尾削除lst.pop() → in-placearr = arr[:-1] → 新規(ビュー)
indexed 削除del lst[i] → in-placenp.delete(arr, i) → 新規
条件削除[x for x in lst if cond]arr[cond] → 高速
サイズ可変×(固定。np.append も新規)

FAQ

Q: in-place で削除したい
A: NumPy は基本不可。配列のサイズを変えるには新規確保が必要です。頻繁に削除するなら listdeque を使い、最後に np.array() 化する設計を。

Q: 削除後に shape を保ちたい
A: 「削除」ではなく「マスクや NaN で無効化」を検討。np.where(cond, arr, np.nan)np.ma.masked_where が有用。

Q: np.delete で負のインデックスは使える?
A: 使えます。np.delete(a, -1) で末尾削除。スライスも np.s_[-3:] で OK。