numpy.reshape()は、既に存在するNumPy配列を、任意のシェイプ(=行数と要素数)の二次元配列に形状変換した新しいNumPy配列を生成する関数です。これと全く同じ機能をもつものにndarray.reshape()というメソッドもあります。
ここでは両方の使い方を詳しく解説します。
1. numpy.reshape, ndarray.reshapeの使い方
numpy.reshape()関数は、既に存在するNumPy配列を、任意のシェイプ(=行数と要素数)の二次元配列に形状変換した新しいNumPy配列を生成する関数です。
書き方:
numpy.reshape(a, newshape, order='C')
パラメーター:
引数 | 型 | 解説 |
a | array_like | 形状変換したい配列を指定します。 |
newshape | int or tuple of ints | 形状を指定します。整数を1つだけ指定すると、その要素数の1次元配列になります。2次元配列以上の形状を指定する場合は、次元の1つは-1を指定することができます。その場合、残りの次元に指定した数値から自動計算してくれます。 |
order(optional) | {‘C’, ‘F’, ‘A’} | ここで指定した順番に配列の要素を読み込み、並び替えていきます。’C’は、読み込みと並び替えをC言語方式で行います。この場合、最後の軸を最も早くインデックスし、最初の軸を最も遅くインデックスします。’F’は、これをFortran方式で行います。この場合、最初の軸を最も早く、最後の軸を最も遅くインデックスします。numpy.reshapeでは、メモリレイアウトには全く関係なく、インデックスの順番にのみ影響します。’A’は、元の配列のメモリレイアウトが’C’なら’C’で、’F’なら’F’で行います。 |
戻り値:
reshaped_array: ndarray 可能な時は、配列の形状を変換した新しい配列を生成します。 それ以外の場合は、形状変換した元の配列のコピーになります。 |
一緒に確認したい属性:
- ndarray.shape: 配列の形状を保持する属性
書き方:
ndarray.reshape(newshape, order='C')
それでは、実際のコードで確認して見ましょう。
1.1. 配列の形状を変換
まず、以下の配列を生成します。
import numpy as np
arr1 = np.arange(1, 13)
arr1
なお、numpy.arangeは『numpy.arange – 連番の配列を生成する』で解説しています。
それでは、この配列をnumpy.reshapeで形状変換してみましょう。
以下のコードでは、行数4、列数3の2次元配列に形状変換しています。
arr2 = np.reshape(arr1, [4, 3]) # 行数4×要素数3の2次元配列に形状変換
arr2
3次元配列以上に形状変換したい時は、以下のコードのように、(奥行き数, 行数, 列数)の順番で指定します。
arr3 = np.reshape(arr1, (3, 2, 2)) # 次元数3×行数2×列数3の3次元配列に形状変換
arr3
注: -1を指定した次元は自動計算
次元のうち一つは、-1を指定するすることができます。-1を指定した次元は、自動的に他の次元から、それに合うように計算してくれます。膨大なデータを持つNumPy行列で計算が面倒な時は、これがとても便利です。
早速以下のコードをご覧ください。
arr4 = np.reshape(arr1, (3, -1)) # 行数だけを指定して列数は自動計算
arr5 = np.reshape(arr1, (3, 2, -1)) # 奥行き数と行数を指定して列数は自動計算
print(arr4, '\n')
print(arr5)
注: 計算が合わない時はエラー
以下のコードでは、要素数12のNumPy配列を5×3(=15)の二次元配列に形状変換しようとしていますが、これでは計算が合わないためエラーになります。
np.reshape(arr1, (5, 3)) # 要素数が12なので5×3(=15)になるような形状変換はできません。
1.2. 第三引数「order」で変換方式を指定
次に、第三引数「order=”」で形状変換の際の順序を変更することができます。
デフォルトのC言語方式では、要素を横に並び替えていきます。これをFortran方式にすると、要素を縦に並び替えていきます。
以下のコードで確認しておきましょう。
arr6 = np.reshape(arr1, (3, -1), order='C') # C言語方式で形状変換
arr7 = np.reshape(arr1, (3, -1), order='F') # FORTRAN方式で形状変換
print(arr6, '\n')
print(arr7)
numpy.reshapeにおけるオプション引数orderは、他の関数やメソッドのorderとは異なりメモリレイアウトとは関係がありませんので覚えておきましょう。
1.3. 要素を変更するときの注意点
なお、numpy.reshape()関数を使う時には注意しておきたい点があります。
それは元の配列でも、形状変換した新しい配列でも、要素に変更を加えると、その変更は双方に反映される点です。
例えば、以下のコードでは、元の配列arr8の要素を1つ変更しています。そして、この変更はarr8を形状変換したarr9にも反映されています。
''' 新しい配列arr8を生成します。'''
arr8 = np.arange(1, 13)
''' arr8を2次元配列に形状変換したarr9を生成します。 '''
arr9 = np.reshape(arr8, (3, 4))
''' 元の配列arr8の最初の要素を変更します。'''
arr8[0] = 100
''' 確認してみましょう。'''
print(arr8, '\n')
print(arr9) # arr9にも変更が反映されます。
新しい配列arr9の要素の変更も、元の配列arr8に反映されます。
''' 形状変換して生成した配列の要素の変更も、元の配列に反映されます。 '''
arr9[1][0] = 50
print(arr9, '\n')
print(arr8)
もし、これを防止したい場合は、numpy.reshape関数で形状変換した配列に続けてndarray.copy使います。
以下のコードをご確認ください。
''' これを回避したい場合は形状変換した配列をcopy()メソッドでコピーします。 '''
arr10 = np.arange(1, 13) # 新しい配列の生成。
arr11 = np.reshape(arr10, (3, 4)).copy() # 形状変換した配列にcopy()メソッドを実行
''' 元の配列の要素を変更します。 '''
arr10[0] = 100
''' 確認しましょう。 '''
print(arr10, '\n') # 元の配列の要素は変更されています。
print(arr11) # copy()メソッドを実行した配列の要素には反映されません。
このように形状変換した配列にndarray.copyを実行している場合は、一方への変更は他方へは影響しません。
2. まとめ
以上が、numpy.reshape()とndarray.reshape()の使い方です。
ndarray.reshape()は、numpy.reshape()と配列を書く位置が異なるだけで全く同じですが、念のためサンプルコードを貼っておきます。
import numpy as np
# 配列を生成
arr = np.arange(1, 13)
print('arr:\n', arr, '\n')
# メソッドなので配列を前に書く
print('arr.reshape()\n', arr.reshape(4, 3), '\n')
# 3次元配列に変換
print('arr.reshape()\n', arr.reshape(3, 2, 2), '\n')
# 列数を自動計算
print('arr.reshape()\n', arr.reshape(2, 2, -1), '\n')
コメント