NumPy の配列は、要素数を変えずに形状だけを変更できます。reshape、flatten、ravel の3つの方法を紹介します。
reshape:任意の形状に変形
reshape() は、配列を指定した形状に変形します。要素の総数が一致していれば、どんな形にでも変えられます。
import numpy as np a = np.arange(12) print(a) # [ 0 1 2 3 4 5 6 7 8 9 10 11] # 3行4列に変形 b = a.reshape(3, 4) print(b) # [[ 0 1 2 3] # [ 4 5 6 7] # [ 8 9 10 11]] # 2行6列に変形 c = a.reshape(2, 6) print(c) # [[ 0 1 2 3 4 5] # [ 6 7 8 9 10 11]]
形状のうち1つの次元を -1 にすると、自動的に計算してくれます。
a = np.arange(12) # 列数だけ指定、行数は自動計算 b = a.reshape(-1, 4) # 3行4列になる print(b.shape) # (3, 4) # 行数だけ指定、列数は自動計算 c = a.reshape(3, -1) # 3行4列になる print(c.shape) # (3, 4)
要素数が合わないとエラーになります。
a = np.arange(12) # a.reshape(5, 3) # ValueError: 12個を5×3=15個にはできない
flatten:1次元配列に変換(コピー)
flatten() は、多次元配列を1次元に平坦化します。元の配列のコピーが返されるため、変更しても元に影響しません。
a = np.array([[1, 2, 3], [4, 5, 6]]) b = a.flatten() print(b) # [1 2 3 4 5 6] # bを変更してもaは変わらない b[0] = 99 print(a[0, 0]) # 1(元のまま)
ravel:1次元配列に変換(ビュー)
ravel() も配列を1次元に平坦化しますが、可能な限りビュー(元データへの参照)を返します。そのため、変更すると元の配列にも影響します。
a = np.array([[1, 2, 3], [4, 5, 6]]) b = a.ravel() print(b) # [1 2 3 4 5 6] # bを変更するとaも変わる b[0] = 99 print(a[0, 0]) # 99(元も変更される)
flatten と ravel の違い
flatten
コピーを返す。安全だがメモリを消費する。元の配列は変更されない
ravel
ビューを返す。高速でメモリ効率が良い。元の配列も変更される可能性がある
読み取り専用で使うなら ravel が効率的です。元の配列を壊したくないなら flatten を選びましょう。
reshape(-1) との関係
reshape(-1) も1次元化に使えます。ravel() と同様にビューを返します。
a = np.array([[1, 2], [3, 4]]) print(a.reshape(-1)) # [1 2 3 4] print(a.ravel()) # [1 2 3 4]
どちらも同じ結果ですが、「平坦化する」という意図を明確にしたいなら ravel() や flatten() を使うほうが読みやすいコードになります。