NumPy配列ndarrayを結合(concatenate, stack, blockなど)

複数のNumPy配列ndarrayを結合(連結)するためには以下の関数を使います。

numpy.concatenate(): 既存の軸に沿って結合 numpy.stack(): 新たな軸に沿って結合 numpy.block(): 配置を指定して結合 numpy.vstack(): 縦に結合 numpy.hstack(): 横に結合 numpy.dstack(): 深さ方向に結合

基本的にはnumpy.concatenate()とnumpy.stack()で対応できるが、特に2次元配列に対してはnumpy.block()やnumpy.vstack(), numpy.hstack()を覚えておくと便利。 ここでは以下の内容について説明します。

numpy.concatenate()の基本的な使い方 結合する配列ndarrayのリストを指定 結合する軸(次元)を指定: 引数axis

numpy.stack()で新たな軸(次元)に沿って結合 numpy.block()で配置を指定して結合 numpy.vstack()で縦に結合 numpy.hstack()で横に結合 numpy.dstack()で深さ方向に結合

そのほかnumpy.r_[]やnumpy.c_[]といった方法もあるが、癖があるのでここでは触れない。詳細は以下の公式ドキュメントを参照。

numpy.r_ — NumPy v1.15 Manual numpy.c_ — NumPy v1.15 Manual

結合ではなく分割については以下の記事を参照。

numpy.concatenate()の基本的な使い方

複数の配列ndarrayを結合する基本的な関数がnumpy.concatenate()。既存の軸(次元)に沿って結合します。

numpy.concatenate — NumPy v1.15 Manual

結合する配列ndarrayのリストを指定

以下の配列を例とします。

import numpy as np

a1 = np.ones((2, 3), int)
print(a1)
# [[1 1 1]
#  [1 1 1]]

a2 = np.full((2, 3), 2)
print(a2)
# [[2 2 2]
#  [2 2 2]]

numpy.ones()やnumpy.full()については以下の記事を参照。

第一引数に結合したいndarrayのリストを指定します。タプルでも問題ありません。

print(np.concatenate([a1, a2]))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]
#  [2 2 2]]

3つ以上でも考え方は同じ。第一引数に指定するリストやタプルの要素数を増やせばよい。

a3 = np.full((2, 3), 3)
print(a3)
# [[3 3 3]
#  [3 3 3]]

print(np.concatenate([a1, a2, a3]))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]
#  [2 2 2]
#  [3 3 3]
#  [3 3 3]]

結合する軸(次元)を指定: 引数axis

第二引数axisに結合する軸(次元)を0始まりで指定します。 デフォルトはaxis=0。2次元配列の場合は最初の軸(0次元目)が行なので縦に結合される。

print(np.concatenate([a1, a2], 0))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]
#  [2 2 2]]

axis=1とすると2番目の軸(1次元目)が列なので横に結合される。

print(np.concatenate([a1, a2], 1))
# [[1 1 1 2 2 2]
#  [1 1 1 2 2 2]]

存在しない軸(次元)を指定するとエラーとなります。新たな軸に対して結合したい場合は後述のnumpy.stack()などを使います。

# print(np.concatenate([a1, a2], 2))
# AxisError: axis 2 is out of bounds for array of dimension 2

結合軸以外の軸のサイズが一致していないとエラーとなります。足りない部分がNaNで埋められたりはしない。

a2_ = np.full((3, 3), 2)
print(a2_)
# [[2 2 2]
#  [2 2 2]
#  [2 2 2]]

print(np.concatenate([a1, a2_], 0))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]
#  [2 2 2]
#  [2 2 2]]

# print(np.concatenate([a1, a2_], 1))
# ValueError: all the input array dimensions except for the concatenation axis must match exactly

2次元以外の配列でも同様。第二引数axisに軸(次元)を指定します。元の配列に存在しない軸では結合できない。

a1 = np.ones(3, int)
print(a1)
# [1 1 1]

a2 = np.full(3, 2)
print(a2)
# [2 2 2]

print(np.concatenate([a1, a2], 0))
# [1 1 1 2 2 2]

# print(np.concatenate([a1, a2], 1))
# AxisError: axis 1 is out of bounds for array of dimension 1

また、元の配列の次元数が異なっている場合はエラーとなります。後述のnumpy.block()やnumpy.vstack()を使うと、1次元配列と2次元配列の縦結合が可能。

a1 = np.ones((2, 3), int)
print(a1)
# [[1 1 1]
#  [1 1 1]]

a2 = np.full(3, 2)
print(a2)
# [2 2 2]

# print(np.concatenate([a1, a2], 0))
# ValueError: all the input arrays must have same number of dimensions

numpy.stack()で新たな軸(次元)に沿って結合

既存の軸(次元)に沿って結合するnumpy.concatenate()に対して、新たな軸に沿って結合する関数がnumpy.stack()。新たな軸に沿って配列を積み重ねる(=stackする)イメージ。

numpy.stack — NumPy v1.15 Manual

第一引数に連結する配列ndarrayのリスト、第二引数axisに結合する軸(次元)を0始まりで指定するのはnumpy.concatenate()と同じ。ただし、axisは結合された配列にとっての軸を指定します。 1次元配列の例 1次元配列を例とします。

a1 = np.ones(3, int)
print(a1)
# [1 1 1]

print(a1.shape)
# (3,)

a2 = np.full(3, 2)
print(a2)
# [2 2 2]

print(a2.shape)
# (3,)

numpy.stack()は新たな軸で結合するので、結果の配列は1次元多い2次元配列となります。 第二引数axisのデフォルトはaxis=0。結果の配列の0次元目(行)に沿って結合される。

print(np.stack([a1, a2]))
# [[1 1 1]
#  [2 2 2]]

print(np.stack([a1, a2], 0))
# [[1 1 1]
#  [2 2 2]]

print(np.stack([a1, a2], 0).shape)
# (2, 3)

axis=1とすると以下の通り。

print(np.stack([a1, a2], 1))
# [[1 2]
#  [1 2]
#  [1 2]]

print(np.stack([a1, a2], 1).shape)
# (3, 2)

結果の配列に存在しない軸を指定するとエラーとなります。

# print(np.stack([a1, a2], 2))
# AxisError: axis 2 is out of bounds for array of dimension 2

axis=-1とすると最後の軸が指定される。この場合はaxis=1と等価。

print(np.stack([a1, a2], -1))
# [[1 2]
#  [1 2]
#  [1 2]]

print(np.stack([a1, a2], -1).shape)
# (3, 2)

次元数ndimが同じでも形状shapeが異なっているとエラーとなります。

a2_ = np.full(4, 2)
print(a2_)
# [2 2 2 2]

print(a2_.shape)
# (4,)

# print(np.stack([a1, a2]))
# ValueError: all input arrays must have the same shape

2次元配列の例 続いて2次元配列を例とします。

a1 = np.ones((3, 4), int)
print(a1)
# [[1 1 1 1]
#  [1 1 1 1]
#  [1 1 1 1]]

print(a1.shape)
# (3, 4)

a2 = np.full((3, 4), 2)
print(a2)
# [[2 2 2 2]
#  [2 2 2 2]
#  [2 2 2 2]]

print(a2.shape)
# (3, 4)

考え方は1次元配列と同様。結果は2次元 + 1次元で3次元配列となります。結果の形状shapeを意識すると理解しやすいです。

print(np.stack([a1, a2]))
# [[[1 1 1 1]
#   [1 1 1 1]
#   [1 1 1 1]]
#
#  [[2 2 2 2]
#   [2 2 2 2]
#   [2 2 2 2]]]

print(np.stack([a1, a2], 0))
# [[[1 1 1 1]
#   [1 1 1 1]
#   [1 1 1 1]]
#
#  [[2 2 2 2]
#   [2 2 2 2]
#   [2 2 2 2]]]

print(np.stack([a1, a2], 0).shape)
# (2, 3, 4)


print(np.stack([a1, a2], 1))
# [[[1 1 1 1]
#   [2 2 2 2]]
#
#  [[1 1 1 1]
#   [2 2 2 2]]
#
#  [[1 1 1 1]
#   [2 2 2 2]]]

print(np.stack([a1, a2], 1).shape)
# (3, 2, 4)


print(np.stack([a1, a2], 2))
# [[[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]]

print(np.stack([a1, a2], 2).shape)
# (3, 4, 2)

結果の配列に存在しない軸を指定するとエラーとなります。

# print(np.stack([a1, a2], 3))
# AxisError: axis 3 is out of bounds for array of dimension 3

axis=-1とすると最後の軸が指定される。この場合はaxis=2と等価。

print(np.stack([a1, a2], -1))
# [[[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]]

print(np.stack([a1, a2], -1).shape)
# (3, 4, 2)

次元数ndimが同じでも形状shapeが異なっているとエラーとなります。

a2_ = np.full((2, 3), 2)
print(a2_)
# [[2 2 2]
#  [2 2 2]]

# print(np.stack([a1, a2_]))
# ValueError: all input arrays must have the same shape

3次元以上のさらに多次元の場合も同様の考え方。

numpy.block()で配置を指定して結合

より直感的に複数の配列を結合できるのがnumpy.block()。

numpy.block — NumPy v1.15 Manual

元の配列をどのように配置するかを示したリストを引数に指定します。 配列を横に並べたリストを指定するとその順番で横に結合される。

a1 = np.ones((2, 3), int)
print(a1)
# [[1 1 1]
#  [1 1 1]]

a2 = np.full((2, 3), 2)
print(a2)
# [[2 2 2]
#  [2 2 2]]

print(np.block([a1, a2]))
# [[1 1 1 2 2 2]
#  [1 1 1 2 2 2]]

2次元のリスト(ネストしたリスト)で縦方向の配置を指定すればそのとおりに結合される。

print(np.block([[a1], [a2]]))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]
#  [2 2 2]]

print(np.block([[a1, a2], [a2, a1]]))
# [[1 1 1 2 2 2]
#  [1 1 1 2 2 2]
#  [2 2 2 1 1 1]
#  [2 2 2 1 1 1]]

引数を3次元にすれば結果も3次元になる。

print(np.block([[[a1]], [[a2]]]))
# [[[1 1 1]
#   [1 1 1]]
#
#  [[2 2 2]
#   [2 2 2]]]

print(np.block([[[a1]], [[a2]]]).shape)
# (2, 2, 3)

以下のように1次元配列を2次元配列を結合することも可能。

a3 = np.full(6, 3)
print(a3)
# [3 3 3 3 3 3]

print(np.block([[a1, a2], [a3]]))
# [[1 1 1 2 2 2]
#  [1 1 1 2 2 2]
#  [3 3 3 3 3 3]]

[]で次元を揃えないとエラーとなるので注意。

# print(np.block([[a1, a2], a3]))
# ValueError: List depths are mismatched. First element was at depth 2, but there is an element at depth 1 (arrays[1])

また、要素数に過不足がある場合もエラーとなります。

# print(np.block([[a1, a2, a3]]))
# ValueError: all the input array dimensions except for the concatenation axis must match exactly

numpy.vstack()で縦に結合

numpy.vstack()は配列を縦(vertical)に結合する関数。

numpy.vstack — NumPy v1.15 Manual

基本的にはaxis=0としたnumpy.concatenate()と同等(numpy/shape_base.py at v1.15.4 · numpy/numpy)。

a1 = np.ones((2, 3), int)
print(a1)
# [[1 1 1]
#  [1 1 1]]

a2 = np.full((2, 3), 2)
print(a2)
# [[2 2 2]
#  [2 2 2]]

print(np.vstack([a1, a2]))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]
#  [2 2 2]]

print(np.concatenate([a1, a2], 0))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]
#  [2 2 2]]

1次元配列に対しては各配列を2次元に拡張してからaxis=0のnumpy.concatenate()が呼ばれるため、結果は2次元配列となります。動作としてはaxis=0としたnumpy.stack()と同等。

a1 = np.ones(3, int)
print(a1)
# [1 1 1]

a2 = np.full(3, 2)
print(a2)
# [2 2 2]

print(np.vstack([a1, a2]))
# [[1 1 1]
#  [2 2 2]]

print(np.stack([a1, a2], 0))
# [[1 1 1]
#  [2 2 2]]

1次元配列が2次元に拡張されるので、2次元配列と1次元配列も結合できます。

a1 = np.ones((2, 3), int)
print(a1)
# [[1 1 1]
#  [1 1 1]]

a2 = np.full(3, 2)
print(a2)
# [2 2 2]

print(np.vstack([a1, a2]))
# [[1 1 1]
#  [1 1 1]
#  [2 2 2]]

numpy.hstack()で横に結合

numpy.hstack()は配列を横(horizontal)に結合する関数。

numpy.hstack — NumPy v1.15 Manual

基本的にはaxis=1としたnumpy.concatenate()と同等(numpy/shape_base.py at v1.15.4 · numpy/numpy)。

a1 = np.ones((2, 3), int)
print(a1)
# [[1 1 1]
#  [1 1 1]]

a2 = np.full((2, 3), 2)
print(a2)
# [[2 2 2]
#  [2 2 2]]

print(np.hstack([a1, a2]))
# [[1 1 1 2 2 2]
#  [1 1 1 2 2 2]]

print(np.concatenate([a1, a2], 1))
# [[1 1 1 2 2 2]
#  [1 1 1 2 2 2]]

1次元配列に対してはaxis=0のnumpy.concatenate()が呼ばれる。

a1 = np.ones(3, int)
print(a1)
# [1 1 1]

a2 = np.full(3, 2)
print(a2)
# [2 2 2]

print(np.hstack([a1, a2]))
# [1 1 1 2 2 2]

print(np.concatenate([a1, a2], 0))

numpy.dstack()で深さ方向に結合

numpy.dstack()は配列を深さ(depth)方向に結合する関数。

numpy.dstack — NumPy v1.15 Manual

基本的にはaxis=2としたnumpy.concatenate()と同等(numpy/shape_base.py at v1.15.4 · numpy/numpy)。 2次元以下の配列は3次元に拡張されてから結合される。

a1 = np.ones((3, 4), int)
print(a1)
# [[1 1 1 1]
#  [1 1 1 1]
#  [1 1 1 1]]

a2 = np.full((3, 4), 2)
print(a2)
# [[2 2 2 2]
#  [2 2 2 2]
#  [2 2 2 2]]

print(np.dstack([a1, a2]))
# [[[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]]

print(np.dstack([a1, a2]).shape)
# (3, 4, 2)

print(np.concatenate([a1.reshape(3, 4, 1), a2.reshape(3, 4, 1)], 2))
# [[[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]
#
#  [[1 2]
#   [1 2]
#   [1 2]
#   [1 2]]]

1次元配列も3次元に拡張される。

a1 = np.ones(3, int)
print(a1)
# [1 1 1]

a2 = np.full(3, 2)
print(a2)
# [2 2 2]

print(np.dstack([a1, a2]))
# [[[1 2]
#   [1 2]
#   [1 2]]]

print(np.dstack([a1, a2]).shape)
# (1, 3, 2)

シェア

関連カテゴリー

Python NumPy

NumPy配列ndarrayの条件を満たす要素数をカウント NumPyで任意の行・列を削除するdeleteの使い方 Pythonで正規化・標準化(リスト、NumPy配列、pandas.DataFrame) Pythonのリストと配列とnumpy.ndarrayの違いと使い分け NumPy配列ndarrayをイミュータブル(書き換え禁止)に設定 NumPy配列ndarrayに新たな次元を追加するnp.newaxis NumPy配列ndarrayとPython標準のリストを相互に変換 pandasからNumPyの関数などを使う方法(pd.np) Python, OpenCV, NumPyで画像のアルファブレンドとマスク処理 NumPy配列ndarrayに要素・行・列を挿入、追加するinsertの使い方 『Pythonデータサイエンスハンドブック』は良書(NumPy, pandasほか) NumPyの配列ndarrayの欠損値np.nanを他の値に置換 NumPyのブロードキャスト(形状の自動変換) NumPy配列ndarrayの次元数、形状、サイズ(全要素数)を取得 Pythonでメソッドチェーンを改行して書く

Last Updated: 6/26/2019, 10:34:03 PM