Skip to content

NumPy Concatenate: np.concatenate、vstack、hstackで配列を結合する

Updated on

配列の結合は数値計算で最も一般的な操作の一つです。データを処理のために分割し、再び組み立てる必要があります。複数のソースから特徴量を一つの行列にロードします。複数のモデルからの予測をアンサンブルのためにスタックします。Pythonのリストを使ってループや+で配列を結合すると、パフォーマンスが低下し、不必要にコピーが作成されます。

NumPyはC言語の速度で動作し、どの軸に沿って連結するかを正確に制御できる配列結合の専用関数を提供します。このガイドではnp.concatenate()np.vstack()np.hstack()np.stack()とそれらのユースケースを説明します。

📚

np.concatenate() -- コア関数

np.concatenate()は既存の軸に沿って配列のシーケンスを結合します。

1D配列

import numpy as np
 
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([7, 8, 9])
 
result = np.concatenate([a, b, c])
print(result)  # [1 2 3 4 5 6 7 8 9]
print(result.shape)  # (9,)

行方向の2D配列(axis=0)

import numpy as np
 
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
 
# 垂直方向にスタック(行を追加)
result = np.concatenate([a, b], axis=0)
print(result)
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]
print(result.shape)  # (4, 2)

列方向の2D配列(axis=1)

import numpy as np
 
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
 
# 水平方向にスタック(列を追加)
result = np.concatenate([a, b], axis=1)
print(result)
# [[1 2 5 6]
#  [3 4 7 8]]
print(result.shape)  # (2, 4)

Shape要件

すべての配列は連結軸以外は同じ形状でなければなりません。

import numpy as np
 
a = np.ones((3, 4))    # 3行、4列
b = np.zeros((2, 4))   # 2行、4列
 
# OK: 行数が異なるが、列数が同じ、axis=0
result = np.concatenate([a, b], axis=0)
print(result.shape)  # (5, 4)
 
# エラー: 列数が異なる
c = np.ones((3, 5))
# np.concatenate([a, c], axis=0)  # ValueError: dimensions don't match

np.vstack() -- 垂直スタッキング

np.vstack()は配列を垂直方向(軸0に沿って)にスタックします。np.concatenate(arrays, axis=0)と同等ですが、1D配列を単一の行として扱います。

import numpy as np
 
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
 
# vstackは1D配列を行として扱う
result = np.vstack([a, b])
print(result)
# [[1 2 3]
#  [4 5 6]]
print(result.shape)  # (2, 3)
 
# 2D配列の場合
c = np.array([[1, 2], [3, 4]])
d = np.array([[5, 6]])
result = np.vstack([c, d])
print(result)
# [[1 2]
#  [3 4]
#  [5 6]]

np.hstack() -- 水平スタッキング

np.hstack()は配列を水平方向にスタックします(2Dの場合は軸1、1Dの場合は軸0)。

import numpy as np
 
# 1D配列: np.concatenateと同様に連結
a = np.array([1, 2, 3])
b = np.array([4, 5])
result = np.hstack([a, b])
print(result)  # [1 2 3 4 5]
 
# 2D配列: 列を追加
c = np.array([[1], [2], [3]])
d = np.array([[4], [5], [6]])
result = np.hstack([c, d])
print(result)
# [[1 4]
#  [2 5]
#  [3 6]]

np.stack() -- 新しい軸を作成

concatenateとは異なり、stack新しい軸に沿って配列を結合し、次元数を1増やします。

import numpy as np
 
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
 
# 新しい軸0に沿ってスタック(デフォルト)
result = np.stack([a, b])
print(result)
# [[1 2 3]
#  [4 5 6]]
print(result.shape)  # (2, 3)
 
# 新しい軸1に沿ってスタック
result = np.stack([a, b], axis=1)
print(result)
# [[1 4]
#  [2 5]
#  [3 6]]
print(result.shape)  # (3, 2)

np.stack()ではすべての入力配列が同じ形状でなければなりません。

関数の比較

関数新しい軸を作成?1D入力の処理
np.concatenate既存(デフォルト0)いいえそのまま連結
np.vstack0(垂直)いいえ1Dを行として扱う
np.hstack1(水平)いいえ1D配列を連結
np.stack新しい軸はい(+1次元)新しい次元を作成
np.column_stack1いいえ1Dを列として扱う
np.row_stack0いいえvstackと同じ

実用的な例

機械学習のための特徴量の結合

import numpy as np
 
# 異なるソースからの特徴量配列
ages = np.array([25, 30, 35, 40])
incomes = np.array([50000, 60000, 75000, 90000])
scores = np.array([720, 680, 750, 800])
 
# 列としてスタックして特徴量行列を作成
X = np.column_stack([ages, incomes, scores])
print(X)
# [[   25 50000   720]
#  [   30 60000   680]
#  [   35 75000   750]
#  [   40 90000   800]]
print(X.shape)  # (4, 3)

バッチ処理結果

import numpy as np
 
# データをバッチで処理し、結果を結合
results = []
for batch_start in range(0, 100, 25):
    batch = np.random.randn(25, 10)  # 25サンプル、10特徴量
    processed = batch * 2 + 1  # 何らかの処理
    results.append(processed)
 
# すべてのバッチを垂直に結合
all_results = np.vstack(results)
print(all_results.shape)  # (100, 10)

画像処理 -- チャネルの結合

import numpy as np
 
height, width = 100, 100
 
# 個別のカラーチャネル
red = np.random.randint(0, 256, (height, width))
green = np.random.randint(0, 256, (height, width))
blue = np.random.randint(0, 256, (height, width))
 
# RGB画像に結合
rgb_image = np.stack([red, green, blue], axis=2)
print(rgb_image.shape)  # (100, 100, 3)

結合データの可視化

異なるソースからの配列を連結した後、PyGWalker (opens in a new tab)を使用すると、Jupyterで結合されたデータセットをインタラクティブに探索できます:

import pandas as pd
import pygwalker as pyg
 
# 連結された配列をDataFrameに変換
df = pd.DataFrame(X, columns=['age', 'income', 'score'])
walker = pyg.walk(df)

FAQ

np.concatenateとnp.stackの違いは何ですか?

np.concatenateは次元数を変えずに既存の軸に沿って配列を結合します。np.stackは新しい軸に沿って配列を結合し、次元を1つ追加します。例えば、2つの(3,)配列をconcatenateでスタックすると(6,)になりますが、stackでは(2, 3)になります。

np.concatenateのaxisとは何ですか?

axisパラメータはどの次元に沿って結合するかを指定します。axis=0は行方向に連結(行を追加)、axis=1は列方向に連結(列を追加)します。2D配列の場合、axis=0は垂直スタッキング、axis=1は水平スタッキングです。

vstack、hstack、concatenateはいつ使うべきですか?

行を追加する(垂直にスタックする)にはvstack、列を追加する(水平にスタックする)にはhstack、任意の軸を指定する必要がある場合はconcatenateを使用します。vstackhstackconcatenateよりも1D配列をより直感的に扱うコンビニエンス関数です。

配列を連結するときにValueErrorが発生するのはなぜですか?

すべての配列は連結軸以外で同じ形状でなければなりません。axis=0に沿って連結する場合、すべての配列は同じ列数でなければなりません。連結前にarray.shapeで形状を確認してください。

異なる次元の配列を連結するにはどうすればよいですか?

まず配列を互換性のある次元に変形します。次元を追加するにはnp.expand_dims(array, axis)を使用するか、array.reshape(new_shape)を使用します。例えば、1D配列を2D配列とvstackするには、1D配列を変形します:array.reshape(1, -1)

まとめ

NumPyは配列結合のための完全なツールキットを提供します:任意の軸に沿った汎用的な結合にはnp.concatenate()、直感的な垂直/水平スタッキングにはnp.vstack()/np.hstack()、新しい次元を作成する必要がある場合はnp.stack()を使用します。concatenateは既存の軸に沿って結合し、stackは新しい軸を作成することを覚えておいてください。次元を慎重に合わせ、一般的な行/列操作には最も読みやすいコードのためにvstack/hstackを使用しましょう。

📚