NumPyの配列の次元の変換方法について

配列の次元の変換について


今回は、NumPyの配列の次元を変換する方法について。

1次元の配列を多次元の配列に変換する方法と、多次元の配列を1次元の配列に変換する方法を学ぶ。

まずは1次元の配列を多次元の配列に変換する方法から。


1次元 → 多次元

1次元の配列を多次元の配列に変換するには、reshape()を使う。

reshape()には、関数として使う方法とndarrayのメソッドとして使う方法がある。

関数のreshape

reshape関数の書式は以下の通り。

numpy.reshape(a, newshape, order='C')

aは変換する配列、newshapeは変換後の配列の形を指定する。

orderは、変換後のデータの並び順を指定する。'C'を指定するとC言語のように処理を行い、行方向優先となる。'F'を指定するとFortranのように処理を行い、列方向優先となる。

orderを指定しない場合は、デフォルトでorder='C'となる。

以下は、arangeで要素数6(0〜5)の配列を作り、reshapeを使って2行3列の2次元配列に変換する例。

(例)orderを指定しない場合

import numpy as np

arr = np.arange(6)
arr = np.reshape(arr, (2,3))
print(arr)

#結果
[[0 1 2]
 [3 4 5]]

(例)order='F'とした場合

import numpy as np

arr = np.arange(6)
arr = np.reshape(arr, (2,3),order='F')
print(arr)

#結果
[[0 2 4]
 [1 3 5]]

メソッドのreshape

NumPyの配列であるndarrayのメソッドとしてreshapeを使う場合、1つ目の引数に変更する配列を指定する必要はない。

reshapeメソッドの書式は以下の通り。

ndarray.reshape(shape, order='C')

メソッドの場合もデフォルトではorder='C'となっている。
import numpy as np

arr = np.arange(6)
print(arr.reshape((2,3)))

#結果
[[0 1 2]
 [3 4 5]]

多次元→1次元




多次元から1次元の配列に変換する時もreshapeを使うことができる。

しかし、もっと有効な方法もある。まずはreshapeでの変換を試し、その後ほかの方法を試すことにする。

reshapeを使う方法

多次元から1次元に変換する時も、基本的な使いかたは1次元から多次元に変換する時と同じ。

違う点は、引数shapeに変換後の形をタプルで指定していた点を、変換後の1次元配列の要素数を数値で指定するという点。

以下は、2行3列の2次元配列をreshapeを使って1次元配列に変換する例。
import numpy as np

a = np.array([[1,2,3],[4,5,6]])
b = a.reshape(6)
print(b)

#結果
[1 2 3 4 5 6]

上記の例では、変換前の2次元配列の要素数が6なので、reshapeの引数で指定する変換後の1次元配列の要素数にも6を指定している。

reshapeの引数に6以外の値を指定するとValueErrorが発生してしまうので注意が必要。

flattenとravel

flattenとravelは、どちらも多次元の配列を1次元の配列に変換することができる。

引数に変換後の1次元配列の要素数を指定する必要がないのでreshapeより使いやすい。

flattenとravelの違いは、flattenは新しくメモリを確保しコピーを作成するが、ravelはコピーを作成しないということ。

以外で具体例を示す。

flattenの使用例

import numpy as np

#①
d2 = np.array([[1,2,3],[4,5,6]])
print('d2:' + str(d2))
print('-' *30)

#②
d1 = d2.flatten()
print('d1:' + str(d1))
print('-' *30)

#③
d1[0] = 100
print('d1:' + str(d1))
print('-' *30)

#④
print('d2:' + str(d2))

#結果
d2:[[1 2 3]
 [4 5 6]]
------------------------------
d1:[1 2 3 4 5 6]
------------------------------
d1:[100   2   3   4   5   6]
------------------------------
d2:[[1 2 3]
 [4 5 6]]

【解説】
①で2行3列の2次元配列を作り、変数d2に代入する。

②でflattenを使ってd2を1次元配列にしてd1に代入

③でd1の1つ目の要素を100に変更

④で元の2次元配列(d2)を表示

③でd1を変更しても、元の2次元配列(d2)は何も変更されていない。

ravelの使用例

import numpy as np

#①
d2 = np.array([[1,2,3],[4,5,6]])
print('d2:' + str(d2))
print('-' *30)

#②
d1 = d2.ravel()
print('d1:' + str(d1))
print('-' *30)

#③
d1[0] = 100
print('d1:' + str(d1))
print('-' *30)

#④
print('d2:' + str(d2))

#結果
d2:[[1 2 3]
 [4 5 6]]
------------------------------
d1:[1 2 3 4 5 6]
------------------------------
d1:[100   2   3   4   5   6]
------------------------------
d2:[[100   2   3]
 [  4   5   6]]

【解説】
①で2行3列の2次元配列を作り、変数d2に代入する。

②でravelを使ってd2を1次元配列にしてd1に代入

③でd1の1つ目の要素を100に変更

④で元の2次元配列(d2)を表示

flattenを使った時とは異なり、次元変換後の変更(③)が変更前の配列にも適用されていることが分かる。(④)

flattenとravelの使い分け

変更前の配列を保持しておきたい時はflattenを使うことになる。

しかし、flattenはコピーを生成するために新たにメモリを確保するので、パフォーマンス的にはravelに劣る。

そのため、コピーが必要ない場合、特に大きなデータを扱う時はravelを使うことでパフォーマンス向上を期待できる。



以上

NumPyの配列の次元の変換方法について

0 件のコメント :