インデックス作成とスライシング

1. 学習内容



2. ストーリー

チャーリーは、10,000行のセンサーデータ行列を分析しています。彼はdata[0:3]を使用して、外れ値の除去のために最初の3行を取り出し、欠損値を-1に設定しています:

PYTHON
subset = data[0:3]
subset[subset == -999] = -1
TEXT
> 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.

掃除を終えたsubsetは、見違えるほどきれいになった。しかし、元のdataを確認してみると、最初の3行も変更されていた!

「スライスはコピーではなく、ビューを返すのよ!」とアリスは説明する。

彼女はチャーリーに、オリジナルに影響を与えない安全な操作を行うためのsubset = data[0:3].copy()の使い方を教える。チャーリーは痛い目に遭って学ぶことになる。NumPyのスライスはデフォルトでメモリを共有する――これがその効率性の源であると同時に、落とし穴の根源でもある。



3. 主要な概念

(1) 基本的なインデックス作成

1次元配列のインデックス指定はPythonのリストと同様に機能します。0から始まり、負のインデックスは-1から数えられます。

PYTHON
import numpy as np

a = np.array([10, 20, 30, 40, 50])
a[0]    # 10
a[-1]   # 50
a[2]    # 30
TEXT
> 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) スライス構文

スライス形式:start:stop:step。3つの部分すべてがオプションです:

略語 対応する語 意味
a[:] a[0:len(a):1] すべての要素
a[2:] a[2:len(a):1] インデックス 2 から末尾まで
a[:3] a[0:3:1] 最初の3つの要素
a[::2] a[0:len(a):2] 1つおきに
a[::-1] a[len(a)-1::-1] 配列を逆順にする
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

PYTHON
a = np.arange(10)  # [0 1 2 3 4 5 6 7 8 9]
a[2:7]             # [2 3 4 5 6]
a[::3]             # [0 3 6 9]
a[::-1]            # [9 8 7 6 5 4 3 2 1 0]
TEXT
> 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.

(3) 2次元インデックス付け

PYTHON
import numpy as np

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

# Row and column
print(a[1])       # [4 5 6 7] — row 1
print(a[1, 2])    # 6 — row 1, col 2

# Sub-matrix
print(a[:2, 1:3])
# [[1 2]
#  [5 6]]
TEXT
> 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.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(4) 3Dインデクシングの直感

3次元配列を「2次元行列の層」と捉えてみてください:

PYTHON
import numpy as np

a = np.arange(24).reshape(2, 3, 4)
print(a.shape)  # (2, 3, 4)

# Layer 0: first 3x4 matrix
print(a[0])
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

# Layer 1: second 3x4 matrix
print(a[1])
# [[12 13 14 15]
#  [16 17 18 19]
#  [20 21 22 23]]

# Single element: a[layer, row, col]
print(a[1, 2, 3])  # 23
TEXT
> 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.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(5) ビューとコピー

スライスは常にビューを返します。 スライスを変更すると、元の配列も変更されます。

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)
view = a[0:2, 1:3]
view[0, 0] = 999

print(a)
# [[  0 999   2   3]
#  [  4   5   6   7]
#  [  8   9  10  11]]
# The original changed!

# Use .copy() for a safe copy
copy = a[0:2, 1:3].copy()
copy[0, 0] = 0
print(a[0, 1])  # 999 — original unchanged by copy
TEXT
> 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.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。


(1) ▶ サンプル

TEXT
> 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次元スライシング (難易度 ⭐)

PYTHON
import numpy as np

a = np.arange(10)

print("Original:", a)
# [0 1 2 3 4 5 6 7 8 9]

print("a[2:8:2]:", a[2:8:2])  # [2 4 6]
print("a[::-1]:", a[::-1])    # [9 8 7 6 5 4 3 2 1 0]
print("a[5:1:-1]:", a[5:1:-1])  # [5 4 3 2]
TEXT
> 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.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。

(2) ▶ サンプル

TEXT
> 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次元部分行列の抽出 (難易度 ⭐⭐)

PYTHON
import numpy as np

a = np.arange(20).reshape(4, 5)
print("Original:\n", a)

# Extract rows 1-2, cols 2-4
sub = a[1:3, 2:5]
print("a[1:3, 2:5]:\n", sub)
# [[ 7  8  9]
#  [12 13 14]]

# Every other row, every other column
print("a[::2, ::2]:\n", a[::2, ::2])
# [[ 0  2  4]
#  [10 12 14]]
TEXT
> 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.
⚠️ 注意: 以下のコードは、ローカルの Python 環境で実行する必要があります。



4. 比較表

(1) スライスのバリエーション

スライス 意味 [0,1,2,3,4,5] の検索結果
[:] すべて [0 1 2 3 4 5]
[2:] インデックス 2 より [2 3 4 5]
[:3] 最初の3件 [0 1 2]
[1:4] インデックス 1 ~ 3 [1 2 3]
[::2] 隔日 [0 2 4]
[::-1] 反転 [5 4 3 2 1 0]

(2) 表示とコピー

機能 スライス (表示) ファンシーインデックス (コピー)
構文 a[1:3] a[[1, 2, 3]]
戻る 表示 コピー
メモリ 共有 新規割り当て
変更は元データに影響しますか はい いいえ
速度 O(1) O(n)

(1) ▶ サンプル:多次元スライシングにおける省略記号の使用(難易度 ⭐⭐)

PYTHON
import numpy as np

arr = np.arange(24).reshape(2, 3, 4)
print("Shape:", arr.shape)

# Ellipsis (...) means "all remaining dimensions"
print("arr[0, ...]:\n", arr[0, ...])
print("arr[..., 0]:\n", arr[..., 0])

# Select last column for all layers and rows
print("arr[..., -1]:\n", arr[..., -1])

出力:

TEXT
形状:(2, 3, 4)
arr[0, ...]:
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
arr[..., 0]:
 [[ 0  4  8]
 [12 16 20]]
arr[..., -1]:
 [[ 3  7 11]
 [15 19 23]]


❓ よくある質問

Q ビューではなくコピーを取得するにはどうすればよいですか?
A .copy() を明示的に使用してください:a[1:3].copy()。あるいは、常にコピーを返す a[[0, 1, 2]] のような「ファンシーインデックス」を使用してください。
Q インデックス指定における省略記号(...)とは何ですか?
A ...(省略記号)は「残りのすべての次元」を表します。 a[..., 0] は、「他のすべての次元について、最後の次元からインデックス 0 を選択する」という意味です。高次元配列で役立ちます。
Q スライスに代入することはできますか?
A はい!a[1:3] = [99, 100]は要素1と2を置き換えます。これは非常に便利な機能で、配列の一部をその場で変更することができます。
Q なぜ a[::-1] だと配列が逆順になるのですか?
A step=-1 は「末尾から始めて逆方向にたどる」という意味だからです。これはコピーではなくビューであるため、逆順にする処理は O(1) で済み、新しいメモリを割り当てる必要はありません。

📖 まとめ



📝 練習問題

  1. 初心者向け(難易度 ⭐)a = np.arange(15) を作成してください。そこから、(a) 最初の 5 つの要素、(b) 最後の 3 つの要素、(c) 偶数番目の要素、(d) 配列を逆順にしたものを抽出してください。

  2. 中級(難易度 ⭐⭐):0~24の値で構成される5×5の配列を作成してください。 そこから、(a) 中央の3×3の部分行列、(b) 最初と最後の行、(c) すべての偶数行と奇数列を抽出してください。部分行列を変更すると元の行列も変化することを確認してください。

  3. 上級(難易度 ⭐⭐⭐):3×4×5の配列を作成してください。... を使用して、すべてのレイヤーと行の最後の列を選択してください。 次に、a[0, ...] を使用して最初のレイヤーを選択してください。それぞれのケースにおいて、... がどのような動作をするかを説明してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%