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 matchnp.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.vstack | 0(垂直) | いいえ | 1Dを行として扱う |
np.hstack | 1(水平) | いいえ | 1D配列を連結 |
np.stack | 新しい軸 | はい(+1次元) | 新しい次元を作成 |
np.column_stack | 1 | いいえ | 1Dを列として扱う |
np.row_stack | 0 | いいえ | 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を使用します。vstackとhstackはconcatenateよりも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を使用しましょう。