NumPyで計算をするためのクラスndarrayは、多次元配列や行列を扱うためのデータ構造です。内部実装では、データ型によってサイズの異なる連続した1次元のメモリ領域が確保されます。

ndarrayのインスタンス変数shapeは、1次元のメモリ領域のどこに指定した多次元配列の要素があるのかを知る手がかりになります。

この記事では、shapeの使い方と読み方を解説します。

ndarray.shape

ndarrayのshapeは、各次元ごとの要素数を示します。 使い方は、Pythonインスタンスと同様arr.shapeとしてプロパティにアクセスするだけです。

まずは配列の情報を取得してみます。

In [1]: import numpy as np

In [2]: a = np.array([5, 3, 8, 9])

In [3]: a
Out[3]: array([5, 3, 8, 9])

In [4]: a.shape
Out[4]: (4,)

np.reshapeで変換すると、shapeは指定した引数に合わせて変更されます。ndarray内部の実装は配列の要素はshapeしか変更されません。単に形状情報だけ変化されているので高速に実行することができます。

np.reshapeについて詳しくは以下の記事を参考にしてください。

配列を形状変換するNumPyのreshapeの使い方 /features/numpy-reshape.html

変更後のshapeは、要素数が同じであればreshapeで指定した引数と同じものに変換されているはずです。

In [5]: a = np.array([5, 3, 8, 9])

In [5]: b = a.reshape((2, 2))

In [6]: b
Out[6]:
array([[5, 3],
       [8, 9]])

In [7]: b.shape
Out[7]: (2, 2)

また、shapeプロパティに代入すると、np.reshapeと同じように配列を変形することができます。

In [8]: a
Out[8]:
array([[5, 3],
       [8, 9]])

In [9]: a.shape
Out[9]: (2, 2)

In [10]: a.shape = (4, 1)

In [11]: a
Out[11]:
array([[5],
       [3],
       [8],
       [9]])

In [12]: c = np.arange(12).reshape((3, 4))
Out[12]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

In [13]: c.shape=(1, 12)

In [14]: c
Out[14]: array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]])

In [15]: c.shape = (13,) # 要素数を誤るとエラーが返る。
---------------------------------------------------------------------------
(エラーメッセージが表示される)

ValueError: cannot reshape array of size 12 into shape (13,)

しかし、特に理由がない限りは明示的にnp.reshapeを使用するほうが無難かと思います。

(R,)や(R,1)という表記について

(R,)という表記は見慣れないかもしれません。Pythonでは要素数が1つのタプルはこのような表記になります。すなわち、ただの1次元配列のshape(R,)のような使い方をする必要があります。一方、1次元配列を転置した縦ベクトルの場合、shape(R, 1)となります。

In [15]: a = np.array([1,2,3,4,5]) # ただの1次元配列

In [16]: a.shape
Out[16]: (5,)

In [17]: b = np.array([[1], [2], [3], [4], [5]]) # 縦ベクトルのようにすると(R,1)の形になる。

In [18]: b.shape
Out[18]: (5, 1)