このブログではデータサイエンスに関わる情報を発信しています。
今回はnumpyの使い方3回目という事で、行列のサイズとスライシングについて解説します。
データサイエンスで必須の部分です。
前回のがまだという人は↓からどうぞ!
【python】Numpyの使い方講座②:行列の演算とブロードキャスト
この講座では全てサンプルコードを記載してあります。
各々のpythonの環境で実際に手を動かしながら読み進める事を推奨しています。
サクッとやりたい方は、google colaboratoryが簡単でおすすめです。
ndarrayのサイズについて
今までに3行3列の行列などと言ってきたのですが、これがndarrayのサイズの事です。
行列の形状だと思っていただければ大丈夫です。
ブロードキャストでは、このサイズが違っていたとしても、条件が揃っていればよしなに計算してくれるんでしたね!
実務では、このサイズについて以下の2点が非常に重要です。
- サイズの把握
- サイズのreshape()
それぞれを深堀りしましょう。
サイズの把握
「今扱っている行列がどんなサイズ?」
「エラーがでてるっぽいけどサイズのせいなの?」
このような点で悩む事もあると思います。そんな時はサクッといまのサイズを確認しましょう。
shape()を使う事で確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import numpy as np # 1次元の配列 arr1 = np.array([1, 2, 3, 4, 5]) print(arr1.shape) # 出力結果: (5,) # 2次元の配列 arr2 = np.array([[1, 2], [4, 5], [7, 8]]) print(arr2.shape) # 出力結果: (3, 2) # 3次元の配列 arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) print(arr3.shape) # 出力結果: (2, 2, 2) |
結果

1次元の配列では、1つの数値が1つの要素になり、要素の数が5つあるため、形状は(5,)
となります。
2次元の配列では、行列の行数が3、列数が2なので、形状は(3, 2)
となります。3次元の配列では、3つの2次元配列があり、各2次元配列は2行2列の行列で構成されているため、形状は(2, 2, 2)
となります。
reshapeしてみよう
実はサイズは後から変更する事ができます。
3行2列を2行3列に変更したりと、要素数に変動がなければreshape()を使う事で可能になります。
1 2 3 4 5 6 7 8 |
# 1次元配列を作成する arr1d = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) # 形状を (3, 3) の2次元配列に変換する arr2d = arr1d.reshape((3, 3)) print("Original 1D array:\n", arr1d) print("Reshaped 2D array:\n", arr2d) |
無事に、1行9列のarrayを3行3列に変換する事ができました!
numpyのスライシング
スライシングは、配列の特定の要素を選択する方法です。
listのn個目の値を取ってき事がある人もいると思いますが、それの行列版だと思ってください。
NumPyのスライシングには、いくつかの異なる方法があります。以下にいくつかの例を示します。
1次元配列のスライシング
まずは以下の1行5列のスライシングを見ていきましょう。
\begin{bmatrix}
1 & 2 & 3 & 4 & 5
\end{bmatrix}
1 2 |
arr = np.array([1, 2, 3, 4, 5]) print(arr[1:4]) |
\begin{bmatrix}
2 & 3 & 4
\end{bmatrix}
この例では、1次元配列を作成し、配列の2番目から4番目の要素を取得しています。
結果は、[2, 3, 4]となります。
2次元配列のスライシング
では続いて2次元配列をスライシングする方法を見ていきましょう。
\begin{pmatrix}
1 & 2 & 3\\
4 & 5 & 6\\
7 & 8 & 9
\end{pmatrix}
1 2 |
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(arr[:2, 1:]) |
\begin{pmatrix}
2 & 3\\
5 & 6\\
\end{pmatrix}
2次元の場合は、arr[n:n, m:m]という形で指定します。
大事なポイントとしては↓になります。
- [n:n]:行の指定。[0:2]と指定すると、1行目と2行目を取得
- [m:m]:列の指定。[1:3]と指定すると、2列目以降4列目未満なので2列目と3列目を取得
ちなみに、全ての行や列を取得したい場合は[:]のように数値を入れずに書くと取得できます。arr[:, :]こんな感じです。
また[1:]この様に書くと、2行・列目以降全てを取得できます。
[:1]この書き方ですと、最初から2行・列目までを取得できます。
3次元配列のスライシング
続いて3次元配列です。
3次元になると複雑になってきますが、指定方法を覚えてしまえば大丈夫です。
1 2 |
# 3次元の行列の作成 arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) |
まずは以下の3次元配列を作成します。
1 2 3 4 5 |
[[[ 1 2 3] [ 4 5 6]] [[ 7 8 9] [10 11 12]]] |
これをスライシングしていきましょう。
3次元の場合はarr[層:層, 行:行, 列:列]という形で指定します。
最初に層をしていする点に注意しましょう!
1 2 3 |
# 3次元のスライシング print(arr[:1, 0:1, :]) |
->
[[[1 2 3]]]
1層目の1行目の全列を取得しました。
3次元にもなると分かり辛くなってきますので、実際に試しながらどこをスライシング指定しているのか覚えていきましょう。
indexで指定する方法
numpyはスライシングだけでなく、indexで指定する事もできます。
個人的にはスライシングの方が使う機会が多く、index指定はあまり使う事はありません。
一応こういうやり方もあるんだ~くらいで聞いてください。
様々な指定方法
NumPyのインデックス指定には、スライシング以外に、↓の3つのタイプがあります。
- 基本的な整数インデックス
- ブールインデックス
- 整数配列インデックス
それぞれを見ていきましょう。
整数index
1 2 3 4 5 |
import numpy as np a = np.array([1, 2, 3, 4]) print(a[0]) # 1 print(a[3]) # 4 |
->
1
4
1次元の場合は単純に[]の中にindexを指定するだけです。
簡単ですね!
続いて2次元の場合を見て見ましょう!
3行3列の行列を基にします。
\begin{pmatrix}
1 & 2 & 3\\
4 & 5 & 6\\
7 & 8 & 9
\end{pmatrix}
1 2 |
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(arr[1]) |
->
[4 5 6]
arr[1]とする事で、2行目の全列の要素を取ってこれました。
これに更に列の指定もすると↓のようになります。
1 2 |
# 2行目の1列目の要素を取得 print(arr[1][0]) |
->
4
無事に2行目の1列目の要素を取得できました。
ちなみにarr[1, 0]の様に書いても同じ結果になります。
ブールindex
ブールインデックスは、ブール値(TrueまたはFalse)を使用して、条件に合致する配列要素にアクセスする方法です。
名前のまんまですね!
1 2 3 |
a = np.array([1, 2, 3, 4, 5]) b = np.array([True, False, True, False, True]) print(a[b]) # [1, 3, 5] |
->
[1 3 5]
Trueで指定した要素だけ取得できました。
整数配列インデックス
整数配列インデックスは、配列内の要素を参照するために、整数配列を使用する方法です。
1 2 3 4 5 |
import numpy as np a = np.array([1, 2, 3, 4]) b = np.array([0, 2]) print(a[b]) # [1, 3] |
->
[1 3]
このように、様々な方法でindexを指定する事ができます。
まとめ
今回はndarrayに対して、スライシングしたり、reshapeしたりと様々な事を学びましたね。
これらを一回で覚えるのは難しいので、実際に自分で手を動かして、ひとつひとつの挙動を確認する事が上達への近道です。
理論だけ覚えても身につきませんからね!
Work illustrations by Storyset