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. 行列を結合する方法

最近更新/作成されたページ