◀ 13.

NumPy 配列結合完全ガイド (concatenate/vstack/hstack)

この記事の要点
  • NumPy の配列結合は np.concatenate が基本。axis 指定で方向を決める
  • np.vstack (vertical) / np.hstack (horizontal) / np.dstack (depth) は次元別エイリアス
  • np.stack は新しい軸 (次元) を追加して結合
  • 形状要件: axis 以外の次元はすべて一致している必要
  • メモリは新規確保される (in-place ではない) → 性能注意

結論: よく使う 4 つのパターン

import numpy as np

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

# 1. 縦方向 (行を増やす)
np.vstack([a, b])
# [[1, 2],
#  [3, 4],
#  [5, 6],
#  [7, 8]]

# 2. 横方向 (列を増やす)
np.hstack([a, b])
# [[1, 2, 5, 6],
#  [3, 4, 7, 8]]

# 3. 汎用 (axis 指定)
np.concatenate([a, b], axis=0)   # = vstack
np.concatenate([a, b], axis=1)   # = hstack

# 4. 新しい軸を追加
np.stack([a, b])                 # shape: (2, 2, 2)

np.concatenate

最も汎用的な関数。複数配列を既存の軸方向に連結します。

np.concatenate(arrays, axis=0, out=None, dtype=None, casting='same_kind')

# 1D
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
np.concatenate([a, b])               # [1, 2, 3, 4, 5, 6]

# 2D, axis=0 (行方向)
A = np.array([[1, 2], [3, 4]])       # (2, 2)
B = np.array([[5, 6]])               # (1, 2)
np.concatenate([A, B], axis=0)
# [[1, 2],
#  [3, 4],
#  [5, 6]]   shape: (3, 2)

# 2D, axis=1 (列方向)
A = np.array([[1, 2], [3, 4]])       # (2, 2)
C = np.array([[5], [6]])             # (2, 1)
np.concatenate([A, C], axis=1)
# [[1, 2, 5],
#  [3, 4, 6]]  shape: (2, 3)

np.vstack / np.hstack / np.dstack

関数axis1D 入力時用途
np.vstack0(N,) → (1, N) に拡張して縦積み行追加
np.hstack1 (1D は 0)(N,) のまま連結列追加 / 1D 連結
np.dstack2(N,) → (1, N, 1)RGB チャネルを重ねる
# 1D を縦積み
np.vstack([np.arange(3), np.arange(3, 6)])
# [[0, 1, 2],
#  [3, 4, 5]]   shape: (2, 3)

# 1D を横結合
np.hstack([np.arange(3), np.arange(3, 6)])
# [0, 1, 2, 3, 4, 5]   shape: (6,)

# 画像チャネル合成 (R, G, B → RGB)
R = np.zeros((100, 100))
G = np.zeros((100, 100))
B = np.zeros((100, 100))
rgb = np.dstack([R, G, B])           # shape: (100, 100, 3)

np.stack: 新しい軸を追加

concatenate は既存の軸方向につなぐのに対し、stack は新しい軸を作って配列を「重ねる」イメージ。

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

np.concatenate([a, b])
# [1, 2, 3, 4, 5, 6]    shape: (6,)

np.stack([a, b])
# [[1, 2, 3],
#  [4, 5, 6]]            shape: (2, 3)  ← 新しい先頭軸

np.stack([a, b], axis=1)
# [[1, 4],
#  [2, 5],
#  [3, 6]]               shape: (3, 2)

np.append

1 要素や別の配列を末尾に追加。内部で concatenate を呼ぶラッパーであり、毎回コピーが発生するためループでの追加には不向きです。

a = np.array([1, 2, 3])
np.append(a, [4, 5])                  # [1, 2, 3, 4, 5]

# 2D
A = np.array([[1, 2], [3, 4]])
np.append(A, [[5, 6]], axis=0)
# [[1, 2],
#  [3, 4],
#  [5, 6]]

# ❌ ループで append は遅い (O(N^2) のメモリコピー)
arr = np.array([])
for i in range(10000):
    arr = np.append(arr, i)           # 巨大データではダメ

# ✅ Python list で集めて最後に np.array へ
buf = []
for i in range(10000):
    buf.append(i)
arr = np.array(buf)

np.r_[ ] と np.c_[ ]

角括弧での結合を提供するインデックス風ヘルパー。スクリプトを短く書くのに便利:

# 1D 連結
np.r_[1:4, [10, 20], 0]
# [1, 2, 3, 10, 20, 0]

# 2D 縦結合 (= vstack)
np.r_[[[1, 2]], [[3, 4]]]

# 2D 横結合 (= hstack)
np.c_[[1, 2, 3], [4, 5, 6]]
# [[1, 4],
#  [2, 5],
#  [3, 6]]

# 行ベクトル化
np.c_[1, 2, 3]
# [[1, 2, 3]]

形状要件

concatenate / vstack / hstack で連結するには、結合軸以外の次元がすべて一致している必要があります:

A = np.zeros((3, 4))     # shape (3, 4)
B = np.zeros((2, 4))     # shape (2, 4)   → axis=0 OK
C = np.zeros((3, 5))     # shape (3, 5)   → axis=0 NG, axis=1 OK
D = np.zeros((3, 4, 2))  # 次元数違い → エラー

np.concatenate([A, B], axis=0)   # OK → (5, 4)
np.concatenate([A, C], axis=0)   # ValueError
np.concatenate([A, C], axis=1)   # OK → (3, 9)
np.concatenate([A, D], axis=0)   # ValueError (次元数不一致)

性能とメモリ

結合は新しいメモリ領域に全要素をコピーします。ループで毎回 concatenate するのは O(N^2) コピーになり大変遅いので、以下のいずれかを推奨:

  1. Python list に append → 最後に np.array(list) で変換
  2. 事前に最大サイズの配列を確保 (np.empty) → スライスで埋める
  3. np.concatenate を 1 回だけ呼ぶ (リスト of 配列を渡す)
# ❌ 遅い
result = np.array([])
for chunk in chunks:
    result = np.concatenate([result, chunk])

# ✅ 一括結合
result = np.concatenate(chunks)

# ✅ pre-allocate
total = sum(c.shape[0] for c in chunks)
result = np.empty(total, dtype=chunks[0].dtype)
i = 0
for c in chunks:
    result[i:i+c.size] = c
    i += c.size

pandas concat との比較

項目NumPy concatenatepandas concat
対象ndarrayDataFrame / Series
軸指定axis=0/1/...axis=0/1
インデックスなしあり (再構築可)
列名のアライン不要 (位置)列名一致でアライン
速度速い (C 実装)NumPy 結合 + ラベル管理

FAQ

Q: 1D 配列を縦に積みたい
A: np.vstack([a, b]) で OK。または np.stack([a, b])。

Q: 結合先のメモリを再利用したい (in-place)
A: NumPy には in-place concatenate はありません。事前に大きい配列を確保しスライス代入が代替。

Q: 文字列配列を結合できますか
A: できます。np.concatenate([['a','b'], ['c','d']])。dtype は配列ごとに固定なので、サイズが大きいものに合わせて昇格します。

Post Share
子ページ

子ページはありません

同階層のページ
  1. 配列の作成
  2. 多次元配列の作成
  3. 要素の参照
  4. 要素の追加
  5. 要素の更新
  6. 要素の削除
  7. ブロードキャスト
  8. 多次元配列の構造の確認
  9. 多次元配列を1次元配列に変換
  10. 1次元配列を多次元配列に変換
  11. NumPy 配列の範囲指定(スライス・多次元・Boolean / Fancy Index)
  12. 平均値の算出
  13. 行列を結合する方法