ブール演算と高度なインデックス作成
1. 学習内容
- ❶ ブールマスク — 条件式を使用して、フィルタリング用の True/False 配列を生成する
- ❷
np.where— 三項条件分岐と要素の置換 - ❸ 高度なインデックス操作 — 整数配列を用いて要素を任意の順序で選択する
- ❹ 複合インデックス — 基本インデックスと高度なインデックスの併用
- ❺ 高度なインデックス機能ではコピーが返される — ビューとの主な違い
2. ストーリー
アリスは10万件の温度測定値を持っており、40°Cを超えるすべての測定値を見つけ出す必要があります。彼女はtemps[temps > 40]と記述すると、即座に結果が得られました。 ボブは驚いてこう言いました。「if文を使ったPythonのループなら少なくとも5行はかかるだろうに、NumPyなら1行で済む。100倍近く速い!」これこそが、NumPyの高度なインデックス機能の真骨頂――簡潔な式で複雑なデータフィルタリングを実現する力です。
3. ブールマスク
(1) ブールマスクとは何か
ブールマスクとは、元の配列と同じ形状を持つ真偽値の配列のことです。NumPyの比較演算子は要素ごとに演算を行い、ブール配列を返します。
import numpy as np
arr = np.array([3, -1, 4, -2, 5])
mask = arr > 0
print(mask) # [ True False True False True]
print(arr[mask]) # [3 4 5]
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(2) 比較演算子
| 演算子 | 意味 | 対応する関数 |
|---|---|---|
> |
より大きい | np.greater |
>= |
以上 | np.greater_equal |
< |
未満 | np.less |
<= |
以下 | np.less_equal |
== |
等しい | np.equal |
!= |
異なる | np.not_equal |
(3) 論理積
論理演算子を使用して複数の条件を組み合わせます。&(and)、|(or)、~(not)を使用してください。Pythonのand/or/not ではなく、論理演算子を使用してください。各条件は括弧で囲む必要があります。
arr = np.array([1, 5, 8, 3, 9, 2])
mask = (arr > 3) & (arr < 8) # 3 < arr < 8
print(arr[mask]) # [5]
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
| 論理演算 | 意味 | 同等の関数 |
|---|---|---|
& |
論理AND | np.logical_and |
| |
論理OR | np.logical_or |
~ |
論理NOT | np.logical_not |
4. np.where と条件付き選択
(1) 3引数形式:np.where(condition, x, y)
条件が True の場合は x から、False の場合は y から要素を返します。
import numpy as np
arr = np.array([-3, 5, -1, 8, -2, 7])
result = np.where(arr > 0, arr, 0)
print(result) # [0 5 0 8 0 7]
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(2) 単引数形:np.where(condition)
条件が True となるインデックスを返します。
indices = np.where(arr > 0)
print(indices) # (array([1, 3, 5]),)
print(arr[indices]) # [5 8 7]
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
5. 高度なインデックス作成
ファンシーインデックスは、整数配列を使用して、任意の順序で要素を選択します。
import numpy as np
a = np.arange(10) # [0 1 2 3 4 5 6 7 8 9]
# Select specific indices
print(a[[0, 3, 7]]) # [0 3 7]
# Select in any order, with repeats
print(a[[5, 5, 1, 9]]) # [5 5 1 9]
# 2D fancy indexing
b = np.arange(12).reshape(3, 4)
print(b[[0, 2]]) # rows 0 and 2
print(b[:, [0, 2, 3]]) # columns 0, 2, 3 for all rows
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(1) ▶ サンプル
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
: ブールマスクによるフィルタリング (難易度 ⭐)
import numpy as np
scores = np.array([55, 82, 91, 47, 73, 100, 68])
passing = scores[scores >= 60]
print("Passing:", passing) # [82 91 73 100 68]
excellent = scores[scores >= 90]
print("Excellent:", excellent) # [91 100]
# Multiple conditions
mid = scores[(scores >= 60) & (scores < 90)]
print("Mid-range:", mid) # [82 73 68]
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(2) ▶ サンプル
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
: 条件付き置換のための np.where (難易度 ⭐⭐)
import numpy as np
# Clip to range: replace values outside [0, 100]
data = np.array([-5, 120, 30, -20, 80, 200])
clipped = np.where(data < 0, 0, np.where(data > 100, 100, data))
print("Clipped:", clipped) # [ 0 100 30 0 80 100]
# Categorize
grades = np.array([45, 72, 88, 55, 91])
letter = np.where(grades >= 85, 'A',
np.where(grades >= 70, 'B',
np.where(grades >= 60, 'C', 'D')))
print("Grades:", letter) # ['D' 'B' 'A' 'D' 'A']
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
6. 比較表
(1) 索引付けの方法
| メソッド | 構文 | 戻り値 | コピーを行うか? | 使用例 |
|---|---|---|---|---|
| 基本スライス | a[1:3] |
表示 | いいえ | サブ配列、連続した範囲 |
| 整数インデックス | a[2] |
スカラー | 該当なし | 単一要素 |
| ブールマスク | a[mask] |
1次元配列 | はい | 条件付きフィルタリング |
| 高度なインデックス機能 | a[[1,3,5]] |
配列 | はい | 任意の順序での選択 |
| np.where | np.where(cond, x, y) |
配列 | はい | 三項選択 |
(2) ブール式と凝った式
| 機能 | ブールマスク | 高度なインデックス作成 |
|---|---|---|
| 構文 | arr[arr > 0] |
arr[[1, 3, 5]] |
| 選択ロジック | 条件ベース | 位置ベース |
| 結果の形状 | 1次元(平坦化) | インデックス配列と同じ形状 |
| 処理速度 | 大きなマスクの場合に高速 | 疎な選択の場合に高速 |
(1) ▶ サンプル:np.ix_ を使った 2 次元ファンシーインデックス(難易度 ⭐⭐)
import numpy as np
arr = np.arange(20).reshape(4, 5)
print("Original:\n", arr)
# Select specific rows and columns
rows = [0, 2, 3]
cols = [1, 3]
result = arr[np.ix_(rows, cols)]
print("Rows [0,2,3], Cols [1,3]:\n", result)
# Modify selected elements
arr[np.ix_([0, 1], [0, 4])] = -1
print("After modification:\n", arr)
出力:
TEXT原文: [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14] [15 16 17 18 19]] 行 [0,2,3]、列 [1,3]: [[ 1 3] [11 13] [16 18]] 修正後: [[-1 1 2 3 -1] [-1 6 7 8 -1] [10 11 12 13 14] [15 16 17 18 19]]
❓ よくある質問
arr[arr > 0] = 0は、すべての正の値を0に設定します。これはインプレース変更です。np.where(arr > 0, 0, arr)は、代わりに新しい配列を返します。arr[mask] は、mask が True となる要素の値を返します。 np.where(mask) は、mask が True である場所の値を返します。arr[mask] は値を取得する場合に、np.where(mask) は位置情報を取得する場合に使用します。arr[[0,2], [1,3]] は (0,1) および (2,3) の要素を選択します。行と列を個別に選択するには、arr[np.ix_([0,2], [1,3])] を使用してください。np.where(mask) を使用すると、元の形状のインデックスを取得できます。📖 まとめ
- ブールマスク:
arr[arr > 0]— 条件に基づいてフィルタリングし、コピーを返す - 論理演算:各条件を括弧で囲んだ
&、|、~を使用してください np.where(cond, x, y): 三項選択 — True の場合は x を、False の場合は y を返すnp.where(cond): 条件が True となるインデックスを返す- 高度なインデックス機能:
arr[[i1, i2, ...]]— 任意の整数インデックスによる選択 - 高度なインデックス機能(ブール演算+高度な機能)は、常にビューではなくコピーを返します
📝 練習問題
-
初心者向け(難易度 ⭐):-10 から 10 までの範囲のランダムな整数 20 個からなる配列を作成してください。ブール値のマスクを使用して、すべての正の値を抽出してください。また、
np.whereを使用して、すべての負の値を 0 に置き換えてください。 -
中級(難易度 ⭐⭐):0~100のランダムな整数からなる5×5の配列を作成してください。 ブール値のマスクを使用して、(a) 50より大きい値を数え、(b) 20より小さい値を20に置き換え、(c)
np.whereを使用して、80より大きいすべての値の行インデックスと列インデックスを抽出してください。 -
上級(難易度 ⭐⭐⭐):生徒の得点を格納する10×4の配列を作成してください(生徒10人、科目4つ)。 高度なインデックス操作を用いて、次のことを行いなさい:(a) すべての科目について、位置 [0,3,7] にいる生徒を選択する、(b) すべての生徒について、位置 [1,3] にある科目を選択する、(c) 総合得点の上位3名の生徒の平均を計算する。