NumPyのconcatenate(), vstack(), hstack(), dstack(), stack()の違い について毎回混乱するのでまとめました。
concatenate()
複数のアレイを、既存の軸に沿って結合する関数です。
基本的に、後述するvstack(), hstack(), dstack()の上位互換がconcatenate()だと思っておけば良さそう。
2つの同shapeなアレイを結合する例を示します。axis
の指定によりどの軸に沿って結合するかを指定します。
a = np.random.random((5, 6, 7, 8)) b = np.random.random((5, 6, 7, 8)) c = np.concatenate([a, b], axis=0) # shape: (10, 6, 7, 8) c = np.concatenate([a, b], axis=1) # shape: (5, 12, 7, 8) c = np.concatenate([a, b], axis=2) # shape: (5, 6, 14, 8) c = np.concatenate([a, b], axis=3) # shape: (5, 6, 7, 16) # 軸を省略したときはaxis=0を指定したのと同じ c = np.concatenate([a, b]) # shape: (10, 6, 7, 8)
axis
で指定した軸に関しては長さがずれていても結合できます。
a = np.random.random((5, 6, 7, 8)) b = np.random.random((5, 6, 70, 8)) c = np.concatenate([a, b], axis=2) # shape: (5, 6, 77, 8)
vstack(), hstack(), dstack()
基本的に以下のように思っておけばよいです。
- vstack():
concatenate(axis=0)
と同じ - hstack():
concatenate(axis=1)
と同じ - dstack():
concatenate(axis=2)
と同じ
hstack()
の例だけ以下に示します。
a = np.random.random((5, 6, 7, 8)) b = np.random.random((5, 6, 7, 8)) c = np.hstack([a, b]) # (5, 12, 7, 8)
しかし、以下に示すように、細部が微妙に異なります。個人的には、これらを覚えるのはかなり困難なので、 事前に結合対象となるアレイのdimを合わせたあとにconcatenate()(または場合に応じてvstack(), hstack(), dstack())を使うほうが 読みやすいコードになるのではないかと思います。
vstack()
vstack()に渡された1-Dアレイ(e.g. (N,))は、結合前に2-Dアレイ(e.g. (1, N,))に拡張されます。よって1-Dアレイと2-Dアレイの結合が可能です。
a = np.random.random((7, )) # (1, 7)に拡張される b = np.random.random((100, 7)) c = np.vstack([a, b]) # shape: (101, 7)
hstack()
hstack()に1-Dアレイと1-Dアレイが渡された場合は、例外的に、連結された1-Dアレイが返ります。
a = np.random.random((5,)) b = np.random.random((5,)) c = np.hstack([a, b]) # shape: (10,)
1-Dアレイと2-Dアレイが渡された場合はエラーになります。
dstack()
dstack()に渡された1-Dアレイ(e.g. (N,))は、結合前に3-Dアレイ(e.g. (1,N,1))に拡張されます。
dstack()に渡された2-Dアレイ(e.g. (M,N))は、結合前に3-Dアレイ(e.g. (M,N,1))に拡張されます。
よって1-Dアレイ、2-Dアレイ、3-Dアレイの結合が可能となることがあります。
a = np.random.random((5,)) # (1, 5, 1)に拡張される b = np.random.random((1,5)) # (1, 5, 1)に拡張される c = np.random.random((1,5,100)) d = np.dstack([a, b, c]) # shape: (1, 5, 1+1+100)
stack()
stack()
はこれまで紹介したコードと異なり、新規に軸を生成します。
a = np.random.random((5, 6, 7)) b = np.random.random((5, 6, 7)) c = np.stack([a, b], axis=0) # shape: (2, 5, 6, 7) c = np.stack([a, b], axis=1) # shape: (5, 2, 6, 7) c = np.stack([a, b], axis=2) # shape: (5, 6, 2, 7) # axis=0を指定したのと同じ c = np.stack([a, b]) # shape: (2, 5, 6, 7)
参考URL
- NumPy配列ndarrayを結合(concatenate, stack, blockなど) | note.nkmk.me
- かなりわかりやすいです。今回紹介しなかった
block()
による結合例も載っています。
- かなりわかりやすいです。今回紹介しなかった