静かなる名辞

pythonとプログラミングのこと



【python】numpyで二次元配列を結合して三次元配列にする方法

 複数の二次元配列を結合して三次元配列に変換する方法について。

np.dstack

 そのものずばりのnp.dstackという関数がある。

numpy.dstack — NumPy v1.14 Manual

>>> a = np.array([[1,2,3],[4,5,6]])
>>> b = np.array([[7,8,9],[10,11,12]])
>>> a
array([[1, 2, 3],
       [4, 5, 6]])
>>> b
array([[ 7,  8,  9],
       [10, 11, 12]])
>>> np.dstack([a,b])
array([[[ 1,  7],
        [ 2,  8],
        [ 3,  9]],

       [[ 4, 10],
        [ 5, 11],
        [ 6, 12]]])

 なんか思ってたのと違う。理解するために色々やってみる。

>>> c = np.dstack([a,b])
>>> a.shape
(2, 3)
>>> c.shape
(2, 3, 2)
>>> c[:,0]
array([[ 1,  7],
       [ 4, 10]])
>>> c[:,1]
array([[ 2,  8],
       [ 5, 11]])
>>> c[:,2]
array([[ 3,  9],
       [ 6, 12]])
>>> c[:,0:,0] # 元の配列を取り出す。適当に書いてたらできた
array([[1, 2, 3],
       [4, 5, 6]])
>>> c[:,0:,1]
array([[ 7,  8,  9],
       [10, 11, 12]])

 わかるようなわからないような感じ。

 ドキュメントによると、

This is equivalent to concatenation along the third axis after 2-D arrays of shape (M,N) have been reshaped to (M,N,1) and 1-D arrays of shape (N,) have been reshaped to (1,N,1).

 つまりこれと同じということ。

>>> a_reshaped = a.reshape((2,3,1))
>>> b_reshaped = b.reshape((2,3,1))
>>> a_reshaped
array([[[1],
        [2],
        [3]],

       [[4],
        [5],
        [6]]])
>>> b_reshaped
array([[[ 7],
        [ 8],
        [ 9]],

       [[10],
        [11],
        [12]]])
>>> np.concatenate((a_reshaped, b_reshaped), axis=2)
array([[[ 1,  7],
        [ 2,  8],
        [ 3,  9]],

       [[ 4, 10],
        [ 5, 11],
        [ 6, 12]]])

 理解はできたが、ほしいものとは違うのだった。

単純なやり方

 普通はこっちがほしいと思うの。

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

       [[ 7,  8,  9],
        [10, 11, 12]]])

 わかりやすい。上との対比で更にわかりやすくするため、np.concatenateで書いてみる。

>>> np.concatenate([[a], [b]], axis=0)
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

 つまりこっちは(M, N)の配列を(1, M, N)にしてaxis=0で結合したのと等価である。