Pythonライブラリ講座

NumPy配列のインデックスとスライスを解説!条件に応じてデータを抽出する方法

前のページ|次のページ

4章ではNumPy配列(ndarray)の『インデックス』と『スライス』および『ブールインデックス参照』について解説します。

初学者の方にもわかりやすいよう丁寧に解説していますので、ぜひ最後までご覧になってください!

本連載講座【Python ライブラリ編】では、データサイエンスに必要なPythonライブラリやその使い方を基礎から学ぶことができます。

NumPyPandasMatplotlibScipySeabornについて、初学者の方にも分かりやすいよう丁寧に解説しています。

さらに、学習した内容を定着させられるように各章演習問題を用意しています。

・Pythonでデータ分析ができるようになりたい

・Pythonの基礎事項は一通り学んだので、さらに深く学びたい

このように考えている方はTech Teacherが運営する【Python ライブラリ編】で、Pythonによるデータサイエンスの学習をすることをお勧めします!

なお、『Pythonについて全く知らない』・『Pythonの基礎事項がまだ分かっていない』という方は、まずコチラの【Python 基礎編】で基礎を一通り学習してからライブラリ編に取り掛かりましょう!

<ライブラリ編 目次>

<ライブラリの基礎>
1章:ライブラリとは

<NumPy>
2章:NumPyの概要と配列(ndarray)
3章:統計量や次元の取得/ソート
4章:配列のインデックス
5章:numpy.whereによる条件制御
6章:配列の結合/分割
7章:乱数

<SciPy>
8章:SciPyの概要と基本操作

<Pandas>
9章:SeriesDataFrame/統計量の取得
10章:データの読み込み/書き込み
11章:データの取り出し/追加
12章:データのソート
13章:データの結合
14章:階層型インデックス
15章:groupbyによる集計
16章:マッピング処理
17章:欠損値の扱い

<Matplotlib>
18章:Matplotlibの概要
19章:pyplotインターフェース
20章:オブジェクト指向インターフェース

<Seaborn>
21章:Seabornの概要と基本操作

インデックスとスライス

Pythonのリストと同様に、NumPyの配列(ndarray)では『インデックス』を用いて要素を参照することができます。

Pythonのリストのインデックスをよく知らないという方向けに、以下の記事ではインデックスを基礎から解説しています。ぜひ参照してください!

ndarrayのインデックス

ndarrayのインデックスは、リストに対するインデックスとほとんど同じように使うことができます。

x = np.arange(0, 100, 10)
print(x)

print(x[3]) #3番目の要素を取り出す
print(x[-1]) #末尾の要素を取り出す
[ 0 10 20 30 40 50 60 70 80 90]
30
90

多次元配列に対するインデックスは、以下のように指定できます。

y = np.arange(9).reshape((3, 3))
print(y)

print(y[0][1]) #0行1列の要素を取り出す
print(y[2]) #2行目をすべて取り出す
[[0 1 2]
 [3 4 5]
 [6 7 8]]
1
[6 7 8]

線形代数で行列に触れたことがある方は、配列を縦に積み重ねてできる行列を考え、行番号と列番号を指定していると考えると分かりやすいと思います。

ndarray インデックス

スライス

スライスを用いることで部分的なデータを取り出すことができます。

スライスとは、配列の要素の一部分を取り出す操作のことです。

配列名[start:stop:step]」とすることで、配列の(start)番目から(stop-1)番目までの要素を(step)個おきに取り出すことができます。

x = np.arange(5)
print(x)

#1番目から2番目までの要素を取り出す
print(x[1:3])

#先頭から3番目までの要素を取り出す
print(x[:4])

#1番目から末尾までの要素を2つおきに取り出す
print(x[1::2])
[0 1 2 3 4]
[1 2]
[0 1 2 3]
[1 3]

ここで注意しておきたいのが、インデックスによる要素の取り出し配列の代入ではコピーではなく参照が行われるという点です。

そのため、スライスなどで参照した配列の要素を変更すると元の配列の要素も変更されます。

arr_origin = np.arange(5)
arr_slice = arr_origin[2:5]
print("元の配列:", arr_origin)
print("スライス:", arr_slice)

#スライスした配列の1番目の要素3を10に変更
arr_slice[1] = 10

#スライスした配列だけでなく、元の配列も変更されている
print("元の配列(変更後):", arr_origin)
print("スライス:(変更後)", arr_slice)
元の配列: [0 1 2 3 4]
スライス: [2 3 4]
元の配列(変更後): [ 0  1  2 10  4]
スライス:(変更後) [ 2 10  4]

配列の要素のコピー

配列の要素を参照するのではなくコピーしたい場合、『np.copy()』を用います。

これにより、コピーした配列を変更しても元の配列が変更されなくなります。

arr_origin = np.arange(5)
arr_slice = np.copy(arr_origin[2:5]) #スライスした配列をコピー

print("元の配列:", arr_origin)
print("スライス:", arr_slice)

#スライスした配列の1番目の要素3を10に変更
arr_slice[1] = 10

#元の配列は変更されていない
print("元の配列(変更後):", arr_origin)
print("スライス:(変更後)", arr_slice)
元の配列: [0 1 2 3 4]
スライス: [2 3 4]
元の配列(変更後): [0 1 2 3 4]
スライス:(変更後) [ 2 10  4]

ブールインデックスによるデータの抽出

ndarrayでは、『ブールインデックス参照』と呼ばれる方法を用いて条件に一致する要素のみを取り出すことができます。

真偽値配列とは

真偽値配列』とは、名前の通り真偽値(True, False)を要素として持つ配列のことです。

ndarrayを含む条件式を書くことで、条件を満たす要素のみがTrueであるような真偽値配列を得ることができます。

以下の例では、条件式を「5以上」とすることで、元の配列で5以上の値を持つ位置がTrueとなっているような配列が得られます。

x = np.array([1, 3, 10, 4, 6, 8, 2, 0, 7])

print(x)
print(x >= 5)
[ 1  3 10  4  6  8  2  0  7]
[False False  True False  True  True False False  True]

真偽値と比較演算子については以下の記事で詳しく解説しています。不安がある方や忘れてしまった方はぜひ参照してください!

ブールインデックス参照

真偽値配列を用いることで、特定の条件を満たす要素のみを取り出す『ブールインデックス参照』を行うことができます。

配列のインデックスとして真偽値配列を指定することでデータを取り出すことができます。

以下の例では、整数を並べた配列から値が5以上の要素のみを取り出しています。

x = np.array([1, 3, 10, 4, 6, 8, 2, 0, 7])

print(x)
print(x[x >= 5]) #ブールインデックス参照
[ 1  3 10  4  6  8  2  0  7]
[10  6  8  7]

また、インデックスとして指定する真偽値配列は別の配列から作成したものでも構いません。

以下の例では、配列xから作成した真偽値配列を用いて、配列yに対してブールインデックス参照を行っています。

x = np.array([1, 3, 10, 4, 6, 8, 2, 0, 7])
y = np.arange(81).reshape((9, 9))
print("x:", x)
print("y:", y)

print()
print(y[x == 10]) #xが10である位置にあるyの要素を取り出す
x: [ 1  3 10  4  6  8  2  0  7]
y: [[ 0  1  2  3  4  5  6  7  8]
 [ 9 10 11 12 13 14 15 16 17]
 [18 19 20 21 22 23 24 25 26]
 [27 28 29 30 31 32 33 34 35]
 [36 37 38 39 40 41 42 43 44]
 [45 46 47 48 49 50 51 52 53]
 [54 55 56 57 58 59 60 61 62]
 [63 64 65 66 67 68 69 70 71]
 [72 73 74 75 76 77 78 79 80]]

[[18 19 20 21 22 23 24 25 26]]

xにおいて10があった3番目の要素がyから取り出されていることが分かります。

4章の練習問題

以下の練習問題を解いてみましょう。

練習問題

問1. 以下の配列xに対して、(1)~(4)を求めてください。ただし、先頭の要素を0番目とします。

x = np.arange(10)

(1) xの3番目の要素
(2) xの2番目から5番目までを取り出した配列
(3) xの先頭から末尾までの値を4つおきに取り出した配列
(4) xの要素を逆順に取り出した配列

問2. 以下の配列xに対して、(1)~(2)を求めてください。

y = np.arange(100)

(1) xから50以下の値のみを取り出した配列
(2) xから7の倍数のみを取り出した配列

解答

問1(クリックして解答を表示)

x = np.arange(10)
print("x:", x)
print()

#(1)
print(x[3])
#(2)
print(x[2:6]) #5番目まで取り出すとき、末尾のインデックスが6となることに注意
#(3)
print(x[::4])
#(4)
print(x[::-1])
x: [0 1 2 3 4 5 6 7 8 9]

3
[2 3 4 5]
[0 4 8]
[9 8 7 6 5 4 3 2 1 0]

問2(クリックして解答を表示)

y = np.arange(100)
print("y:", y)
print()

#(1)
print(y[y <= 50])
#(2)
print(y[y % 7 == 0])
y: [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
 96 97 98 99]

[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50]
[ 0  7 14 21 28 35 42 49 56 63 70 77 84 91 98]

次のページへ