NumPy配列結合完全ガイド|concatenate・stack・block・append全関数の使い方とサンプルコード

 

NumPyでは複数の配列を結合するための様々な関数が用意されています。本記事では、concatenatestackblockappendなど、配列結合の全手法を実践的なサンプルコードとともに詳しく解説します。

NumPy配列結合の基本概念

NumPyの配列結合には、大きく分けて以下の方法があります:

  • concatenate: 既存の軸に沿って配列を結合
  • stack: 新しい軸を作成して配列を積み重ね
  • block: ブロック状に配列を組み合わせ
  • append: 配列の末尾に要素を追加

concatenate:既存軸での配列結合

基本的な使い方

import numpy as np

# 1次元配列の結合
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.concatenate([arr1, arr2])
print("1次元結合:", result)
# 出力: [1 2 3 4 5 6]

axis=0での行方向結合

# 2次元配列の行方向結合
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
result = np.concatenate([arr1, arr2], axis=0)
print("行方向結合:")
print(result)
# 出力:
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

axis=1での列方向結合

# 2次元配列の列方向結合
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
result = np.concatenate([arr1, arr2], axis=1)
print("列方向結合:")
print(result)
# 出力:
# [[1 2 5 6]
#  [3 4 7 8]]

複数配列の同時結合

# 3つ以上の配列を同時結合
arr1 = np.array([1, 2])
arr2 = np.array([3, 4])
arr3 = np.array([5, 6])
result = np.concatenate([arr1, arr2, arr3])
print("複数配列結合:", result)
# 出力: [1 2 3 4 5 6]

vstack・hstack:便利な結合関数

vstack(垂直結合)

# 垂直方向の結合
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.vstack([arr1, arr2])
print("vstack結果:")
print(result)
# 出力:
# [[1 2 3]
#  [4 5 6]]

hstack(水平結合)

# 水平方向の結合
arr1 = np.array([[1], [2]])
arr2 = np.array([[3], [4]])
result = np.hstack([arr1, arr2])
print("hstack結果:")
print(result)
# 出力:
# [[1 3]
#  [2 4]]

vstackとhstackの2次元配列での応用

# 2次元配列でのvstack
matrix1 = np.array([[1, 2], [3, 4]])
matrix2 = np.array([[5, 6]])
v_result = np.vstack([matrix1, matrix2])
print("2次元vstack:")
print(v_result)

# 2次元配列でのhstack
matrix1 = np.array([[1, 2], [3, 4]])
matrix2 = np.array([[5], [6]])
h_result = np.hstack([matrix1, matrix2])
print("2次元hstack:")
print(h_result)

stack:新しい軸での配列結合

基本的なstack操作

# stackで新しい軸を作成
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.stack([arr1, arr2])
print("stack結果:")
print(result)
print("形状:", result.shape)
# 出力:
# [[1 2 3]
#  [4 5 6]]
# 形状: (2, 3)

axis指定でのstack

# axis=0でのstack(デフォルト)
arr1 = np.array([1, 2])
arr2 = np.array([3, 4])
stack_0 = np.stack([arr1, arr2], axis=0)
print("axis=0:", stack_0)

# axis=1でのstack
stack_1 = np.stack([arr1, arr2], axis=1)
print("axis=1:", stack_1)
# 出力:
# axis=0: [[1 2]
#          [3 4]]
# axis=1: [[1 3]
#          [2 4]]

2次元配列でのstack

# 2次元配列のstack
matrix1 = np.array([[1, 2], [3, 4]])
matrix2 = np.array([[5, 6], [7, 8]])
result = np.stack([matrix1, matrix2])
print("2次元stack:")
print(result)
print("形状:", result.shape)
# 形状: (2, 2, 2) - 3次元配列になる

dstack・column_stack・row_stack

dstack(深度方向結合)

# dstackで深度方向に結合
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
result = np.dstack([arr1, arr2])
print("dstack形状:", result.shape)
print("dstack結果:")
print(result)
# 形状: (2, 2, 2)

column_stack(列として結合)

# 1次元配列を列として結合
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.column_stack([arr1, arr2])
print("column_stack:")
print(result)
# 出力:
# [[1 4]
#  [2 5]
#  [3 6]]

row_stack(行として結合)

# row_stackはvstackの別名
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.row_stack([arr1, arr2])
print("row_stack:")
print(result)
# vstackと同じ結果

block:ブロック状配列結合

基本的なblock操作

# 2x2ブロック構造の作成
arr1 = np.array([[1, 2]])
arr2 = np.array([[3, 4]])
arr3 = np.array([[5, 6]])
arr4 = np.array([[7, 8]])

result = np.block([[arr1, arr2],
                   [arr3, arr4]])
print("block結果:")
print(result)
# 出力:
# [[1 2 3 4]
#  [5 6 7 8]]

異なるサイズのブロック結合

# 異なるサイズのブロック
top = np.array([[1, 2, 3]])
bottom_left = np.array([[4], [5]])
bottom_right = np.array([[6, 7], [8, 9]])

result = np.block([[top],
                   [bottom_left, bottom_right]])
print("異なるサイズblock:")
print(result)
# 出力:
# [[1 2 3]
#  [4 6 7]
#  [5 8 9]]

3次元ブロック

# 3次元ブロック構造
block1 = np.ones((2, 2, 2))
block2 = np.zeros((2, 2, 2))
result = np.block([[[block1, block2]]])
print("3次元block形状:", result.shape)
# 形状: (2, 2, 4)

append:配列への要素追加

1次元配列でのappend

# 基本的なappend
arr = np.array([1, 2, 3])
result = np.append(arr, 4)
print("append結果:", result)
# 出力: [1 2 3 4]

# 複数要素の追加
result = np.append(arr, [4, 5, 6])
print("複数append:", result)
# 出力: [1 2 3 4 5 6]

2次元配列でのappend

# 2次元配列のappend(axis指定)
arr = np.array([[1, 2], [3, 4]])

# 行の追加(axis=0)
new_row = np.array([[5, 6]])
result = np.append(arr, new_row, axis=0)
print("行追加:")
print(result)

# 列の追加(axis=1)
new_col = np.array([[7], [8]])
result = np.append(arr, new_col, axis=1)
print("列追加:")
print(result)

appendの注意点

# axisを指定しない場合は1次元化される
arr_2d = np.array([[1, 2], [3, 4]])
result = np.append(arr_2d, [5, 6])
print("axis未指定:", result)
# 出力: [1 2 3 4 5 6] (1次元化される)

実践的な応用例

データフレーム的な操作

# 学生データの結合例
students_a = np.array([['Alice', 85], ['Bob', 92]])
students_b = np.array([['Charlie', 78], ['David', 88]])

# 学生データの縦結合
all_students = np.vstack([students_a, students_b])
print("全学生データ:")
print(all_students)

# 科目データの横結合
math_scores = np.array([['85'], ['92'], ['78'], ['88']])
combined = np.hstack([all_students, math_scores])
print("科目追加後:")
print(combined)

時系列データの結合

# 時系列データの結合
jan_data = np.array([10, 15, 12, 18])
feb_data = np.array([20, 22, 19, 25])
mar_data = np.array([30, 28, 32, 35])

# 月別データの結合
quarterly_data = np.concatenate([jan_data, feb_data, mar_data])
print("四半期データ:", quarterly_data)

# 2次元として結合(月×日)
monthly_matrix = np.vstack([jan_data, feb_data, mar_data])
print("月別マトリックス:")
print(monthly_matrix)

画像データ風の結合

# 画像風データの結合
image1 = np.ones((3, 3))
image2 = np.zeros((3, 3))
image3 = np.full((3, 3), 0.5)

# 水平結合(横並び)
horizontal = np.hstack([image1, image2, image3])
print("水平結合形状:", horizontal.shape)

# 垂直結合(縦並び)
vertical = np.vstack([image1, image2, image3])
print("垂直結合形状:", vertical.shape)

# ブロック結合(2x2配置)
block_image = np.block([[image1, image2],
                        [image3, image1]])
print("ブロック結合形状:", block_image.shape)

パフォーマンス比較

結合方法による速度差

import time

# 大きな配列での性能テスト
arr1 = np.random.rand(1000, 1000)
arr2 = np.random.rand(1000, 1000)

# concatenate
start = time.time()
result1 = np.concatenate([arr1, arr2], axis=0)
time1 = time.time() - start

# vstack
start = time.time()
result2 = np.vstack([arr1, arr2])
time2 = time.time() - start

print(f"concatenate時間: {time1:.6f}秒")
print(f"vstack時間: {time2:.6f}秒")

メモリ効率的な結合

# リストからの一括結合(効率的)
arrays = [np.random.rand(100) for _ in range(10)]
efficient = np.concatenate(arrays)

# 逐次結合(非効率)
inefficient = arrays[0]
for arr in arrays[1:]:
    inefficient = np.concatenate([inefficient, arr])

print("効率的結合形状:", efficient.shape)
print("非効率結合形状:", inefficient.shape)

エラーハンドリングと注意点

形状不一致エラー

# 形状エラーの例
try:
    arr1 = np.array([[1, 2, 3]])
    arr2 = np.array([[4, 5]])  # 異なる列数
    result = np.concatenate([arr1, arr2], axis=0)
except ValueError as e:
    print("形状エラー:", e)

# 正しい結合方法
arr1 = np.array([[1, 2, 3]])
arr2 = np.array([[4, 5, 6]])  # 同じ列数
result = np.concatenate([arr1, arr2], axis=0)
print("正しい結合:", result)

安全な結合関数

def safe_concatenate(arrays, axis=0):
    """安全な配列結合"""
    if not arrays:
        return np.array([])
    
    # 形状チェック
    shapes = [arr.shape for arr in arrays]
    if axis == 0:
        # 行結合:列数が同じかチェック
        if len(set(shape[1:] for shape in shapes)) > 1:
            print("警告: 列数が異なります")
            return None
    elif axis == 1:
        # 列結合:行数が同じかチェック
        if len(set(shape[0] for shape in shapes)) > 1:
            print("警告: 行数が異なります")
            return None
    
    return np.concatenate(arrays, axis=axis)

# 使用例
arr1 = np.array([[1, 2]])
arr2 = np.array([[3, 4, 5]])  # 異なる列数
result = safe_concatenate([arr1, arr2], axis=0)

結合関数の使い分けガイド

目的別選択指針

# データの種類と目的に応じた選択例

# 1. 同じ形状の配列を単純結合
arr1 = np.array([1, 2])
arr2 = np.array([3, 4])
simple_concat = np.concatenate([arr1, arr2])

# 2. 行列として積み重ね
stack_result = np.vstack([arr1, arr2])

# 3. 列として並べる
column_result = np.column_stack([arr1, arr2])

# 4. 新しい次元で結合
new_dim = np.stack([arr1, arr2])

print("単純結合:", simple_concat)
print("行積み重ね:", stack_result)
print("列並べ:", column_result)
print("新次元:", new_dim)

選択フローチャート

def choose_concat_method(purpose):
    """結合方法の選択ガイド"""
    guide = {
        "同じ軸で結合": "concatenate",
        "行として積み重ね": "vstack",
        "列として並べる": "hstack",
        "新しい軸で結合": "stack",
        "ブロック構造": "block",
        "末尾に追加": "append"
    }
    return guide.get(purpose, "concatenateを推奨")

# 使用例
print("行として積み重ね:", choose_concat_method("行として積み重ね"))

まとめ

NumPy配列の結合には様々な方法があり、目的に応じて適切な関数を選択することが重要です。

主要関数の特徴:

  • concatenate: 汎用的な結合、axis指定で柔軟な操作
  • vstack/hstack: 直感的な垂直/水平結合
  • stack: 新しい次元での結合、形状変更あり
  • block: 複雑なブロック構造の作成
  • append: 配列への要素追加

選択のポイント:

  1. 形状維持: 元の次元を保つならconcatenate
  2. 新次元: 新しい軸が必要ならstack
  3. 直感性: 分かりやすさならvstack/hstack
  4. 複雑性: ブロック構造ならblock

注意事項:

  • 結合する配列の形状を事前に確認
  • 大量データではメモリ使用量に注意
  • パフォーマンスが重要な場合は事前測定

適切な結合方法を選択することで、効率的で読みやすいNumPyコードが書けるようになります。データ処理や科学計算において、これらの関数を使い分けて柔軟な配列操作を実現してください。