numpy.reshapeで配列の形状を変換する

配列の形状を変換するための reshape

ある配列を変換して別の形状にするには、numpy.reshape を使用します。

同じく形状を変換する numpy.resize との違いも合わせて紹介します。

numpy.reshape関数の使い方

例えば、サイズ9の配列を3×3の2次元配列に計上を変換するには、次のようにします。

import numpy as np

# [1..9] の配列を 3×3 に変換
a = np.arange(1, 10)
b = np.reshape(a, (3, 3))

print(a) 
print(b)
# [1 2 3 4 5 6 7 8 9]
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]

1次元配列が2次元配列に変換されていることがわかります。なお、numpy.reshape で変換されてできたndarrayの各要素は、元の配列の要素と同じ参照を持つため、値を書き換えると互いに影響が及びます。以下の例で確認してみます。

import numpy as np

# [1..9] の配列を 3×3 に変換
a = np.arange(1, 10)
b = np.reshape(a, (3, 3))

# 配列の値を書き換える
a[0] = 0
b[2][2] = 10

# 書き換えた値が相互に反映されている
print(a) 
print(b)
# [0  2  3  4  5  6  7  8 10]
# [[0  2  3]
#  [4  5  6]
#  [7  8 10]]

numpy.reshape は参照を保持した状態で形状を変換していることを覚えておきましょう。では、指定できるパラメータを見ていきます。

numpy.reshape関数のパラメータ

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

パラメータ 説明
a array_like 変換元となる配列(ndarrayやPythonのリストなど)を指定します。
newshape int, タプル 新しい形状(shape)を指定します。元の形状と互換性がなければなりません。整数値の場合、そのサイズの1次元配列となります。
order string 省略可能。インデックスの順序を指定します。'C','F','A' から指定します。デフォルトは'C'です。

return値として、形状が変換されたndarrayが返されます。

newshapeの指定方法

newshapeのパラメータは、いくつかの指定方法があります。ここで変換できない形状を指定するとエラーになってしまいます。

int値で指定した場合には、1次元配列に変換されます。

タプルで指定した場合には、多次元配列へ変換されます。タプルの値で-1を指定すると、変換元の要素数に合わせて(変換前要素数=変換後要素数となるように)自動で値が決定します。

import numpy as np

# 3×2の配列を1次元配列に変換
a = np.array([[1, 2], [3, 4], [5, 6]])
b = np.reshape(a, 6)
print(b) # [1 2 3 4 5 6]

# 要素数8の配列を2×4の配列に変換
# タプルで-1を指定することで自動的に決定できる
c = np.arange(8)
d = np.reshape(c, (2, 4))
e = np.reshape(c, (2, -1)) # -1で自動決定
f = np.reshape(c, (-1, 4)) # -1で自動決定
print(d)
print(e)
print(f)
# [[0 1 2 3]
#  [4 5 6 7]]

ここでは2次元配列への変換を例にしていますが、3次元配列以上でも同じように形状変換ができます。

order

orderは変換後のインデックスの順序を指定するためのパラメータです。要素数12の配列を3×4の2次元配列に変換で、orderがどのように影響するか確認してみます。

import numpy as np

# order="C","F" で確認
a = np.arange(12)
c = np.reshape(a, (3, 4), order="C")
f = np.reshape(a, (3, 4), order="F")

print(c)
print(f)
# order="C"(デフォルト)の場合
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
# order="F"の場合
# [[ 0  3  6  9]
#  [ 1  4  7 10]
#  [ 2  5  8 11]]

order="F"の場合は、1列目から順に値が埋められていっているのが確認できます。基本はデフォルトのorder="C"を使用するのが良いと思います。

ndarray.reshape関数の使い方

reshape関数は ndarray にも定義されています。使い方は numpy.reshape と同じです。ndarrayから形状を変換するには、ndarray.reshape が使えることを覚えておきましょう。

import numpy as np

a = np.arange(9)
b = a.reshape((3, 3)) # np.reshape(a, (3, 3))と同義
print(b)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

resize関数との違い

numpy.resize を使用すると、ある配列から形状変換を行うことが可能です。numpy.reshape との大きな違いは以下の2点です。

  1. numpy.resize は指定された形状(shape)の配列のコピーが返される。
  2. numpy.resize は異なる要素数の配列に変換してもエラーになりません。値の切り捨てや繰り返しによって調整されます。

では numpy.resize を使った配列の形状変換を行ってみます。

import numpy as np

# [0, 1, 2] を 4×3の配列に変換
# 変換前の要素数が足りていないので
# 値の繰り返しで埋められる
a = np.arange(3)
b = np.resize(a, (3, 4))

print(b)
# 0, 1, 2 .. の繰り返し
# [[0 1 2 0]
#  [1 2 0 1]
#  [2 0 1 2]]

# 要素数100の配列を 3×3の配列に変換
# 要素数が多いので要素が切り捨てられる
c = np.arange(100)
d = np.resize(c, (3, 3))

print(d)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

変換前と変換後で配列の要素数が異なっていても、エラーにならず変換されていることが確認できます。

また、変換後の配列はコピーとして生成されるため別の配列です。reshapeと違い、変換前後の配列の値を書き換えても影響しません。

import numpy as np

a = np.zeros(9)
b = np.resize(a, (3, 3))

# 形状変換後の配列を書き換える
b[1, 1] = 1

# 形状変換前の値には影響していない
print(a)
# [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
print(b)
# [[ 0.  0.  0.]
#  [ 0.  1.  0.]
#  [ 0.  0.  0.]]

以上2点の違いに注意しましょう。

なお、reshape と同様 ndarray.resize も存在しています。使い方は同じです。

まとめ

  • reshape は、配列の形状(shape)を変換する。
  • reshape によって得られる形状変換後の配列の値は、変換前の値の参照を持っている。
  • reshape は、形状変換前と変換後の要素数が同じでないとエラーになる。
  • resize は指定された形状(shape)の配列のコピーが返される。
  • resize は異なる要素数の配列に変換してもエラーにならず、値の切り捨てや繰り返しによって調整される。
  • reshaperesize は、ndarray にも定義されている。

以上。

参考URL