Python NumPy 転置行列〜行と列の入れ替え〜

スポンサーリンク
Pythonプログラム
記事内に広告が含まれています。

ndarrayで転置したいときってありますよね!てか、めっちゃ使うので参考にしてください!

ここでは、転置行列について、初心者でもわかりやすく説明します!
イメージしやすいように図も踏まえて説明しす。

2次元配列の転置行列

転置行列とは、簡単に言えば「行と列を入れ替える」ことですね。
先に実際にプログラムを書いて確かめてみましょう。
まずは、転置行列のイメージをつけるために、2次元配列の転置行列からです。

0 ~ 19までの値が入った4×5の行列を作ってみましょう。

import numpy as np
arr = np.arange(20).reshape((4, 5))
print(arr)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]

出来ましたね。
このように一行ずつ順番に並んでいるのがわかります。
では、この配列を転置してみましょう。
転置させるには、transpose関数か「.T」を使います。

arr_T = arr.T
arr_transpose = arr.transpose()

print("arr.T = ", arr_T)
print("arr.transpose = ", arr_transpose)
arr.T =  [[ 0  5 10 15]
          [ 1  6 11 16]
          [ 2  7 12 17]
          [ 3  8 13 18]
          [ 4  9 14 19]]
arr.transpose =  [[ 0  5 10 15]
                  [ 1  6 11 16]
                  [ 2  7 12 17]
                  [ 3  8 13 18]
                  [ 4  9 14 19]]

何が起こったかわかりましたか?

「4×5」の配列が、「5×4」の配列になりましたね。
また、要素の「0, 6, 12, 18」を軸に各要素が入れ替わっていることがわかります。
(「1 ⇔ 5」、「7 ⇔ 11」のように替わります。)

この「「0, 6, 12, 18」を軸に」ってのは、(0, 0)、(1, 1)、(2, 2)、(3, 3)と、行と列の値、インデックスの値が一致している要素です。
数学の世界では、各要素が(i, j)という座標で表示されて、この i と j が同じ、つまり、「i = j」の要素が転置の軸になります。
イメージ的には下図のようになります。

赤丸のところが、軸に当たります。
これらを軸として、ほかの要素を対称となる位置に配置させます。
上記の数学的に言うと、

(i , j) ⇒ (j, i)

とする感じですね。

と、まあこんな風に転置行列を考えていた人も多いと思います。
しかし、2次元配列まではこのままのイメージでOKですが、3次元配列では少しややこしくなります。
3次元配列を理解するために、「transpose関数」の中身について、解説したいと思います。

transpose関数

まず、transpose関数では、引数を渡せます。
で、何の引数を渡すかというと、「入れ替える軸の順番」を渡せます。

ここでの軸とは、「行」であったり、「列」であったりです。
上記の2次元配列だと下図のようなイメージです。

行が0軸、列が1軸となっています。

で、transpose関数に渡す引数は、これらの軸に対して、順番を与え、その順番通りに行と列を入れ替えます。

ちょっと言葉では説明しにくいので、実際に見てみましょう。
まず、上記の2次元配列を見てみます。に見てみましょう.

arr
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])

の2次元配列に対して、以下のようにtranspose関数に引数を渡します。

arr.transpose(0, 1)
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])

上記の例だと、変わりがないことがわかります。
では、下記のように0と1を入れ替えるとどうなるでしょうか?

arr.transpose(1, 0)
array([[ 0,  5, 10, 15],
       [ 1,  6, 11, 16],
       [ 2,  7, 12, 17],
       [ 3,  8, 13, 18],
       [ 4,  9, 14, 19]])

4×5の配列から5×4の配列に変わったことがわかります。
また、要素も列ごとに(横に)0, 1, 2, ・・・と順番に配置されていたのが、今度は行ごとに(縦に)順番に配置されていることがわかります。

では、transpose関数の中身を見ていきましょう。

こういった感じで、元の配列の0軸目の順番、1軸目の順番を、(0, 1)、または、(1, 0)と指定していくことで、狙い通りの行と列の入れ替えができます。

上の例ですと、最初は0軸目を0番、1軸目を1番にしているので変わりはありません。
二つ目は0軸目を1番、つまり、0軸目だったものを1軸目に、1軸目を0番、つまり、1軸目だったものを0軸目にしています。

その結果、(i, j)=(j, i)となります。

では、応用して3次元配列について見てみましょう。

3次元配列の転置行列

まず、3次元配列を作りましょう。

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

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

では、いろいろな順番でやってみましょう。

arr3.transpose(1,0,2)
array([[[ 0,  1,  2,  3],
        [12, 13, 14, 15]],

       [[ 4,  5,  6,  7],
        [16, 17, 18, 19]],

       [[ 8,  9, 10, 11],
        [20, 21, 22, 23]]])

(2, 3, 4)の配列が(3, 2, 4)の配列になりましたね。

では、続いて見てみましょう。

arr3.transpose(2,1,0)
array([[[ 0, 12],
        [ 4, 16],
        [ 8, 20]],

       [[ 1, 13],
        [ 5, 17],
        [ 9, 21]],

       [[ 2, 14],
        [ 6, 18],
        [10, 22]],

       [[ 3, 15],
        [ 7, 19],
        [11, 23]]])

こちらも(2, 3, 4)が(4, 3, 2)になってます。
ちなみにこれはtranspose関数に引数を指定しなかったとき、つまり、転置行列と同じ時です。

では続いて、

arr3.transpose(0,2,1)
array([[[ 0,  4,  8],
        [ 1,  5,  9],
        [ 2,  6, 10],
        [ 3,  7, 11]],

       [[12, 16, 20],
        [13, 17, 21],
        [14, 18, 22],
        [15, 19, 23]]])

こちらは(2, 3, 4)から(2, 4, 3)となっております。
これも順番どおりですね。

ただ、わたし的にわからないことがあります。
以下の2パターンの時です。

arr3.transpose(1,2,0)
arr3.transpose(2,0,1)

この二つの出力はこうなります。(出力するときはprint関数使うか、一つずつ実行してください。)

array([[[ 0, 12],
        [ 1, 13],
        [ 2, 14],
        [ 3, 15]],

       [[ 4, 16],
        [ 5, 17],
        [ 6, 18],
        [ 7, 19]],

       [[ 8, 20],
        [ 9, 21],
        [10, 22],
        [11, 23]]])

array([[[ 0,  4,  8],
        [12, 16, 20]],

       [[ 1,  5,  9],
        [13, 17, 21]],

       [[ 2,  6, 10],
        [14, 18, 22]],

       [[ 3,  7, 11],
        [15, 19, 23]]])

(2, 3, 4)の配列でtranspose関数に(1, 2, 0)と引数を渡したら、(4, 2, 3)となると思っていたのに、(3, 4, 2)となりました。

また、(2, 3, 4)の配列でtranspose関数に(2, 0, 1)と引数を渡したら、(3, 4, 2)となると思っていたのに、(4, 2, 3)となりました。

なんで?って感じです。
この二つの出力結果と予想していたものがちょうどてれこになってるのはわかったんですけど、原理がわかんないです。

どなたか詳しい方教えてくださーい!!

まとめ

転置行列について、解説しました。

また、今回どんだけ調べても、納得いかないこと、理解できないことがあったので、初めて質問を投げかけることをしてしまいました。
面目ねえ。。。

誰か答えてくれると嬉しいな。。。


NumPyの基礎は以下で紹介してますので、復習がてらご覧ください。

NumPyの基礎 ~NumPyの構造・特徴編~
Python NumPy インデックス参照とスライシング
Python NumPy ndarray多次元配列のインデックス参照とスライス
Python NumPy ndarrayにおけるブールインデックス参照
Python NumPy:ndarrayのファンシーインデックス参照

今回もいつもと同様、「Pythonによるデータ分析入門」から学び取りました。

一緒に、データサイエンティスト、機械学習、AIについて学んでいきましょう!!

継続は山なり!!
ちりも積もれば力となる!!

コメント

タイトルとURLをコピーしました