NumPy:【次元を操作】する方法いろいろ


サマリ

  • np.reshape
    • 形状変換
    • -1は残り全部と言う意味
  • np.squeeze
    • 次元削除
  • .T
    • 転置
    • 次元を逆に並び替え
  • np.transpose
    • .Tより柔軟な転置
    • 次元を任意に並び替え
  • np.newaxis
    • 次元を増やす
    • 次元追加
  • ファンシーインデックス参照を使った並び替え
    • 次元並び替え

前提

サンプルコード

reshape(形状変換)

基本

import numpy as np
a = np.arange(12).reshape(3,4)
b = a.reshape(2,6)
print(a)
print(a.shape)
print(b)
print(b.shape)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
(3, 4)
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]]
(2, 6)
  • 中身のデータより形状の(3,4)や(2,6)に注目する
  • (3,4)
    • 3×4=12のデータがある
  • (2,6)
    • 2×6=12のデータになった
    • データこの数は変わらず
    • 形が2行6列に変化させる

次元数を変更

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

 [[ 6  7]
  [ 8  9]
  [10 11]]

 [[12 13]
  [14 15]
  [16 17]]]
(3, 3, 2)
  • 2次元から3次元に変換することもできる
  • (3,6)
    • 3×6=18個のデータ
  • (3,3,2)
    • 3x3x2=18個のデータ
    • データの個数が一致していれば2次元から3次元に変換できる

うまく行かないパターン

import numpy as np
a = np.arange(12).reshape(4,3)
print(a.shape)
b = a.reshape(2,2)
(4, 3)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-175-ea6b1b62f1e1> in <module>
      2 a = np.arange(12).reshape(4,3)
      3 print(a.shape)
----> 4 b = a.reshape(2,2)

ValueError: cannot reshape array of size 12 into shape (2,2)
  • (4,3)
    • 4×3=12個のデータ
  • (2,2)
    • 2×2=4個のデータに変換せよと言う指定
    • データの個数が一致しないので形状変換(reshape)はエラーになる
    • 2×6とか6×2とか3×4とかはOK

次元削除

import numpy as np
a = np.arange(18).reshape(3,3,2)
b = a.reshape(3,-1)
c = a.reshape(-1)
print(a.shape)
print(b.shape)
print(c.shape)
(3, 3, 2)
(3, 6)
(18,)
  • 同様に全体の個数があっているなら次元数を削減(次元削除)できる
  • ここでは個数の細かい計算を省ける「-1」を紹介
    • 「-1」は残り全部と言う意味
  • (3,3,2)
    • 3x3x2=18個のデータ
  • (3,-1)
    • 3x?=18個のデータになるようにうまくやる
    • つまり?は6になる
    • (3,6)と等価
  • (-1)
    • この場合は(18)と等価
  • 次元削除については次項のnp.squeezeも参照してください

np.squeeze(次元削除)

データ作成

import numpy as np
a = np.array([[2, 3, 2]])
print(a)
print(a.shape)
print(a.ndim)
[[2 3 2]]
(1, 3)
2
  • [[2, 3, 2]]
    • 2次元データになるように[[…]]としています
    • 1次元[2,3,2]とデータの中身は同じです
  • shapeの結果(1,3)
    • 1次元目の要素数が1つになっています
  • ndimの結果2
    • ndarray(NumPy配列)としては2次元データとなっています

次元削除

b = a.squeeze()
print(b)
print(b.shape)
print(b.ndim)
[2 3 2]
(3,)
1
  • (1,3)から(3, )に次元削除された
    • np.reshapeと違って要素数が1の次元を削除するような次元削除です
  • ndimの結果も1で1次元ndarrayになった
  • (1, 3)でも(3, )でも入っているデータは{2,3,2}で同じです
  • 参考
    • (1, 3)と(3, )の違いについては下記の記事で説明しています

.T(転置、次元が逆順になる)

実際の数字で見る

import numpy as np
a = np.random.randint(1,10, (2,3))
b = a.T
print(a)
print(a.shape)
print(b)
print(b.shape)
[[9 7 1]
 [5 7 3]]
(2, 3)
[[9 5]
 [7 7]
 [1 3]]
(3, 2)
  • 横長が縦長になった感じ
  • イメージを横に置いたトランプを想像
    • ×:回転させる
    • 〇:角だけテーブルにくっつけてパタンと縦長になるように
  • でもこのイメージは2次元の場合にしか使えない
転置(.T)のイメージ

各次元の要素数に注目する

import numpy as np
a = np.random.randint(1,10, (2,3,4))
b = a.T
print(a.shape)
print(b.shape)
(2, 3, 4)
(4, 3, 2)
  • (2,3,4)から(4,3,2)
    • 並び順が変わっている
    • 転置とは並び順を変えるものと理解できる
  • 転置を理解するために
    • 3次元以上になると実際のデータがどう入れ替わるかイメージするのは難しい
    • 各次元の数字(要素数)に注目すると転置の新しい概念が得られる

np.transpose(転置、次元を任意に並び替え)

データ作成

import numpy as np
a = np.arange(24).reshape(3,4,2)
print(a.shape)
(3, 4, 2)
  • 元の(3,4,2)
    • 1次元目(0)の要素数が3
    • 2次元目(1)の要素数が4
    • 3次元目(2)の要素数が2

転置実行

b = a.transpose(1,2,0)
print(b.shape)
(4, 2, 3)
  • 前項の「.T」の動作が理解できていれば簡単
  • .transposeの引数(1,2,0)
    • 1次元目の要素数を「元2次元目(1)の要素数4」に
    • 2次元目の要素数を「元3次元目(2)の要素数2」に
    • 3次元目の要素数を「元1次元目(0)の要素数3」に
      • 結果(4,2,3)になる
  • まとめ
    • 次元の要素数を任意で並び替えできる
      (並び替えなので3x4x2=24個のデータ数は変わらない)
    • 並び順を指定できる
      (前項の「.T」は逆順にするだけで、指定はできない)

np.newaxis(次元を増やす)

import numpy as np
a = np.arange(10).reshape(2,5)
b = a[np.newaxis,:,:]
c = a[:,:,np.newaxis]
print(a.shape)
print(b.shape)
print(c.shape)
(2, 5)
(1, 2, 5)
(2, 5, 1)
  • b
    • 先頭に新しい次元が加わっている
  • c
    • 末尾に新しい次元が加わっている
  • 参考
    • どんな場合に役に立つかは(2, )と(1,2)の違いを理解することが近道
    • (2, )と(1,2)の違いの説明した下記記事にヒントあり

ファンシーインデックス参照による次元並び替え

データ作成

import numpy as np
a = np.arange(18).reshape(3,6)
print(a)
print(a.shape)
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]]
(3, 6)
  • 形状(3,6)のndarray(NumPy配列)を作成
  • np.arangeを利用したので、各行の数字がキレイに並んでいるます
  • 一番右の列を移動させるので注目
b = a[:, [0, 5, 1, 2, 3, 4]]
print(b)
print(b.shape)
[[ 0  5  1  2  3  4]
 [ 6 11  7  8  9 10]
 [12 17 13 14 15 16]]
(3, 6)
  • [0,5,1,2,3,4]
    • ここで指定している数字は列番号(0から始まる)
    • 5(6列目)を2列目に移動すると言う指定
  • 転置と比較して理解を深めてください
    • 転置は次元を並び替え
    • この例では列を並び替え
    • 両者をきっちり理解することで、次元に対する理解度がUPします


Posted by futa