データ整形が楽になる!NumPy `column_stack`で効率的な配列操作

2025-05-27

どんな機能?

簡単に言うと、与えられた複数の配列を、それぞれが新しい配列の1つの列になるように積み重ねて、1つの大きな2次元配列を作る機能です。

特徴

  • 次元の整合性: 結合するすべての配列は、最初の次元(行数)が同じである必要があります。
  • 2次元配列の扱い: 2次元配列が入力された場合、それらはそのまま水平方向(列方向)に結合されます。これは numpy.hstack() と似ています。
  • 1次元配列の扱い: 1次元配列が入力された場合、まずそれを2次元の列(例: [1, 2, 3][[1], [2], [3]] のように)に変換してから結合します。

使い方

基本的な構文は以下の通りです。

numpy.column_stack(tup)
  • tup: 結合したい配列のシーケンス(タプルやリストなど)を指定します。

いくつかの例を見てみましょう。

1次元配列を結合する例

import numpy as np

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

c = np.column_stack((a, b))
print(c)

出力:

[[1 4]
 [2 5]
 [3 6]]

この例では、ab という2つの1次元配列が、それぞれ結果の配列の1列目と2列目として結合されています。

2次元配列を結合する例

import numpy as np

x = np.array([[1, 2],
              [3, 4]])
y = np.array([[5],
              [6]])

z = np.column_stack((x, y))
print(z)
[[1 2 5]
 [3 4 6]]

この例では、2次元配列 xy が列として結合されています。y はすでに2次元の列の形をしているため、そのまま x の右隣に結合されます。

  • numpy.concatenate(): 任意の軸に沿って配列を結合します。column_stackconcatenate を使って実装することも可能ですが、特定の目的(列としての結合)に特化したより便利な関数です。
  • numpy.hstack(): 配列を水平方向(列方向)に結合します。ただし、column_stack は1次元配列を自動的に列に変換してから結合するのに対し、hstack は1次元配列をそのまま水平方向に結合します。
  • numpy.vstack(): 配列を垂直方向(行方向)に結合します。


ValueError: all input arrays must have same number of dimensions (入力配列の次元数が一致していません)

これは column_stack ではあまり起こりませんが、numpy.concatenate() など他の結合関数でよく見られるエラーです。column_stack は1次元配列を自動的に2次元の列に変換するため、次元数の不一致は通常問題になりません。

トラブルシューティング

  • 各配列の ndim 属性や shape 属性を確認し、結合したい軸の次元が一致しているか確認してください。
  • このエラーが出た場合、column_stack 以外の結合関数(例: numpy.concatenate()numpy.stack()) を使用していて、その関数の次元数に関する要件を満たしていない可能性があります。

ValueError: all input arrays must have the same first dimension (入力配列の最初の次元がすべて同じである必要があります)

これが numpy.column_stack() で最もよく遭遇するエラーです。column_stack は配列を列として結合するため、結合されるすべての配列の「行数」(つまり最初の次元の長さ)が同じである必要があります。


import numpy as np

a = np.array([1, 2, 3]) # 行数 3
b = np.array([4, 5])   # 行数 2 (a と異なる)

try:
    c = np.column_stack((a, b))
    print(c)
except ValueError as e:
    print(f"エラー: {e}")
エラー: all input arrays must have the same first dimension

トラブルシューティング

  • 別の結合方法を検討する
    もし行数が異なる配列を結合したい場合は、column_stack は適していません。
    • 異なる行数を持つ配列を結合したい場合は、例えばPandasのDataFrameを使用して、インデックスに基づいて結合するなどの方法が考えられます。
    • あるいは、NaNなどで埋めてから結合することも可能です。
  • 配列の長さを合わせる
    • 不足している要素を追加する
      必要に応じて、短い方の配列に適切な値(例: 0、NaNなど)を加えて長さを合わせます。
    • 余分な要素を削除する
      長い方の配列から不要な要素を削除して長さを合わせます。
    • データソースを確認する
      元のデータソースに問題がないか確認し、結合したいデータが本来同じ長さであるべきか検討します。
  • 各配列の行数を確認する
    array.shape を使って、各配列の行数(shapeの最初の要素)がすべて同じであることを確認してください。

型の不一致 (Dtype Mismatch)

これはエラーメッセージとしては直接表示されにくいですが、結合後の配列のデータ型が意図したものと異なる場合があります。numpy.column_stack() は、結合される配列のデータ型を「アップキャスト」します。例えば、整数型と浮動小数点数型を結合すると、結果は浮動小数点数型になります。


import numpy as np

a = np.array([1, 2, 3], dtype=np.int32)
b = np.array([4.0, 5.0, 6.0], dtype=np.float64)

c = np.column_stack((a, b))
print(c)
print(c.dtype)
[[1. 4.]
 [2. 5.]
 [3. 6.]]
float64

a は整数型でしたが、b が浮動小数点数型なので、結果の cfloat64 になっています。

トラブルシューティング

  • 意図しない型変換を避ける
    必要に応じて、事前にすべての配列のデータ型を統一しておくか、結合後に astype() メソッドで明示的に変換します。
  • 結合後のデータ型を確認する
    result_array.dtype で結合後の配列のデータ型を確認します。

特に1次元配列と2次元配列を混在させている場合、結果の形状が期待と異なることがあります。column_stack は1次元配列を列ベクトルとして扱うため、この挙動を理解しておくことが重要です。


import numpy as np

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

c = np.column_stack((a, b))
print(c)
print(c.shape)
[[1 4]
 [2 5]
 [3 6]]
(3, 2)

a は1次元配列ですが、column_stack によって (3, 1) のように変換され、b と結合されて (3, 2) の配列になります。これは意図通りの動作ですが、1次元配列がどのように扱われるかを理解していないと混乱する可能性があります。

  • 明示的に形状を操作する
    必要であれば、reshape()atleast_2d() などを使って、事前に配列の形状を明示的に調整してから column_stack を使用します。
  • 入力配列の形状を確認する
    array.shape で各入力配列の形状を確認し、column_stack がどのように動作するかを考慮して、期待される出力形状を事前に予測します。


例1:最も基本的な使い方(1次元配列の結合)

最も一般的な使い方は、複数の1次元配列を結合して、それぞれが結果の2次元配列の1列になるようにすることです。

import numpy as np

# 1次元配列を2つ作成
data1 = np.array([10, 20, 30, 40, 50])
data2 = np.array([1, 2, 3, 4, 5])

print("data1 の形状:", data1.shape)
print("data2 の形状:", data2.shape)

# column_stack を使って結合
# data1 が1列目、data2 が2列目になる
combined_array = np.column_stack((data1, data2))

print("\n結合後の配列:\n", combined_array)
print("結合後の配列の形状:", combined_array.shape)

出力

data1 の形状: (5,)
data2 の形状: (5,)

結合後の配列:
 [[10  1]
 [20  2]
 [30  3]
 [40  4]
 [50  5]]
結合後の配列の形状: (5, 2)

解説
data1data2 はどちらも1次元配列(形状が (5,))。column_stack はこれらを自動的に「列ベクトル」として扱い(内部的には形状が (5, 1) のように)、水平方向に結合します。結果として、行数5、列数2の2次元配列が作成されます。

例2:3つ以上の1次元配列の結合

column_stack は、2つだけでなく、任意の数の配列を結合できます。

import numpy as np

age = np.array([25, 30, 35, 40])
height = np.array([170, 175, 160, 180])
weight = np.array([65, 70, 55, 80])

# 複数の配列を結合
personal_data = np.column_stack((age, height, weight))

print("結合後の個人データ:\n", personal_data)
print("結合後の個人データの形状:", personal_data.shape)

出力

結合後の個人データ:
 [[ 25 170  65]
 [ 30 175  70]
 [ 35 160  55]
 [ 40 180  80]]
結合後の個人データの形状: (4, 3)

解説
age, height, weight の3つの1次元配列が、それぞれ結果の配列の1列目、2列目、3列目として結合されています。これにより、各行が一人の人物のデータ(年齢、身長、体重)を表すようなデータセットを簡単に作成できます。

例3:2次元配列の結合

入力がすでに2次元配列である場合も column_stack を使用できます。この場合、基本的に numpy.hstack() と同じように動作します。

import numpy as np

matrix_A = np.array([[1, 2],
                     [3, 4]])

matrix_B = np.array([[5],
                     [6]])

print("matrix_A の形状:\n", matrix_A.shape)
print("matrix_B の形状:\n", matrix_B.shape)

# column_stack を使って結合
# matrix_A の右側に matrix_B が結合される
combined_matrix = np.column_stack((matrix_A, matrix_B))

print("\n結合後の行列:\n", combined_matrix)
print("結合後の行列の形状:", combined_matrix.shape)

出力

matrix_A の形状: (2, 2)
matrix_B の形状: (2, 1)

結合後の行列:
 [[1 2 5]
 [3 4 6]]
結合後の行列の形状: (2, 3)

解説
matrix_A(2, 2) の行列、matrix_B(2, 1) の列ベクトルです。どちらも2次元配列であり、行数(最初の次元)が同じ2であるため、column_stack はこれらの配列を水平方向に結合します。

例4:1次元配列と2次元配列の混合結合

column_stack は、1次元配列と2次元配列が混在していても正しく処理します。1次元配列は自動的に2次元の列に変換されます。

import numpy as np

# 1次元配列
id_column = np.array([101, 102, 103])

# 2次元配列(例えば、特徴量データ)
feature_data = np.array([[5.1, 3.5],
                         [4.9, 3.0],
                         [6.3, 3.3]])

print("id_column の形状:", id_column.shape)
print("feature_data の形状:", feature_data.shape)

# id_column を最初の列として feature_data と結合
dataset = np.column_stack((id_column, feature_data))

print("\n結合後のデータセット:\n", dataset)
print("結合後のデータセットの形状:", dataset.shape)

出力

id_column の形状: (3,)
feature_data の形状: (3, 2)

結合後のデータセット:
 [[101.   5.1   3.5]
 [102.   4.9   3. ]
 [103.   6.3   3.3]]
結合後のデータセットの形状: (3, 3)

解説
id_column は1次元配列ですが、column_stack が自動的に (3, 1) の列ベクトルに変換し、feature_data の左側に結合されます。これにより、id を含む完全なデータセットが作成されます。また、型が異なる(整数と浮動小数点数)場合、結果の配列はより広い範囲をカバーできる型(この場合は float64)に自動的に変換されます。

前述の「よくあるエラー」で説明したように、結合する配列の行数が異なる場合、ValueError が発生します。

import numpy as np

a = np.array([1, 2, 3])      # 3行
b = np.array([4, 5, 6, 7]) # 4行 (行数が異なる)

try:
    c = np.column_stack((a, b))
    print(c)
except ValueError as e:
    print(f"\nエラーが発生しました: {e}")
    print("行数が異なるため、column_stack は失敗します。")
エラーが発生しました: all input arrays must have the same first dimension
行数が異なるため、column_stack は失敗します。


numpy.concatenate()

numpy.concatenate() は、指定した軸(axis)に沿って複数の配列を結合する最も汎用的な関数です。column_stack と同じ結果を得るには、結合したい1次元配列を明示的に2次元の列ベクトルに変換し、axis=1 を指定する必要があります。

特徴

  • axis パラメータで結合する軸を明示的に指定できる。
  • 任意の次元の配列を結合できる。

column_stack と同等の操作

import numpy as np

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

# column_stack を使った場合
c_col_stack = np.column_stack((a, b))
print("column_stack の結果:\n", c_col_stack)
print("形状:", c_col_stack.shape)

# concatenate を使った場合
# 1次元配列を明示的に2次元の列ベクトルに変換する (np.newaxis または reshape)
a_col = a[:, np.newaxis] # または a.reshape(-1, 1)
b_col = b[:, np.newaxis] # または b.reshape(-1, 1)

c_concat = np.concatenate((a_col, b_col), axis=1)
print("\nconcatenate の結果:\n", c_concat)
print("形状:", c_concat.shape)

出力

column_stack の結果:
 [[1 4]
 [2 5]
 [3 6]]
形状: (3, 2)

concatenate の結果:
 [[1 4]
 [2 5]
 [3 6]]
形状: (3, 2)

使い分け

  • しかし、concatenate は、より複雑な次元操作や、結合したい軸を細かく制御したい場合に適しています。
  • 1次元配列を自動的に列に変換してくれる column_stack の方が、多くの場合で簡潔です。

numpy.hstack()

numpy.hstack() は、配列を水平方向(列方向)に積み重ねます。2次元配列を結合する場合には column_stack と同じ挙動をしますが、1次元配列を扱う場合は異なります。

特徴

  • 1次元配列を結合すると、新しい1次元配列を生成する(column_stack とは異なる点)。
  • 配列を水平方向(第2軸、列方向)に結合する。

column_stack との比較

import numpy as np

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

# column_stack を使った場合
c_col_stack = np.column_stack((a, b))
print("column_stack (1D) の結果:\n", c_col_stack)
print("形状:", c_col_stack.shape)

# hstack を使った場合 (1D配列はそのまま連結される)
c_hstack_1d = np.hstack((a, b))
print("\nhstack (1D) の結果:\n", c_hstack_1d)
print("形状:", c_hstack_1d.shape)

# 2次元配列の場合 (column_stack と hstack は同じ結果になる)
matrix_A = np.array([[1, 2], [3, 4]])
matrix_B = np.array([[5], [6]])

c_col_stack_2d = np.column_stack((matrix_A, matrix_B))
c_hstack_2d = np.hstack((matrix_A, matrix_B))

print("\ncolumn_stack (2D) の結果:\n", c_col_stack_2d)
print("形状:", c_col_stack_2d.shape)
print("\nhstack (2D) の結果:\n", c_hstack_2d)
print("形状:", c_hstack_2d.shape)

出力

column_stack (1D) の結果:
 [[1 4]
 [2 5]
 [3 6]]
形状: (3, 2)

hstack (1D) の結果:
 [1 2 3 4 5 6]
形状: (6,)

column_stack (2D) の結果:
 [[1 2 5]
 [3 4 6]]
形状: (2, 3)

hstack (2D) の結果:
 [[1 2 5]
 [3 4 6]]
形状: (2, 3)

使い分け

  • 2次元配列を水平に結合する場合は、どちらを使っても結果は同じです。
  • 1次元配列を「水平に連結」したい場合(より長い1次元配列にしたい場合)は hstack が適しています。
  • 1次元配列を「列」として結合したい場合は column_stack が便利です。

numpy.stack()

numpy.stack() は、新しい軸に沿って配列を結合します。これにより、入力配列よりも1次元高い配列が生成されます。column_stack のように列として結合するには、特定の axis を指定する必要があります。

特徴

  • すべての入力配列は同じ形状である必要がある。
  • 新しい軸を作成し、その軸に沿って配列を結合する。

column_stack と同等の操作

import numpy as np

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

# column_stack を使った場合
c_col_stack = np.column_stack((a, b))
print("column_stack の結果:\n", c_col_stack)
print("形状:", c_col_stack.shape)

# stack を使った場合
# axis=1 を指定することで、新しい2次元配列の2番目の軸 (列) に沿って積み重ねられる
c_stack = np.stack((a, b), axis=1)
print("\nstack(axis=1) の結果:\n", c_stack)
print("形状:", c_stack.shape)

出力

column_stack の結果:
 [[1 4]
 [2 5]
 [3 6]]
形状: (3, 2)

stack(axis=1) の結果:
 [[1 4]
 [2 5]
 [3 6]]
形状: (3, 2)

使い分け

  • column_stack のような「列としての結合」は、stack(axis=1) で実現できますが、column_stack の方が意図が明確で簡潔です。
  • stack は、入力配列の次元を増やして結合したい場合に強力です。

numpy.c_ は、スライス構文を使って配列を結合するための便利なオブジェクトです。これは column_stack と非常に似た挙動をします。

特徴

  • column_stack と同様に、1次元配列を自動的に列ベクトルに変換する。
  • スライス構文を使用し、視覚的に直感的。

column_stack と同等の操作

import numpy as np

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

# column_stack を使った場合
c_col_stack = np.column_stack((a, b))
print("column_stack の結果:\n", c_col_stack)
print("形状:", c_col_stack.shape)

# c_ を使った場合
c_c_ = np.c_[a, b]
print("\nc_ の結果:\n", c_c_)
print("形状:", c_c_.shape)

出力

column_stack の結果:
 [[1 4]
 [2 5]
 [3 6]]
形状: (3, 2)

c_ の結果:
 [[1 4]
 [2 5]
 [3 6]]
形状: (3, 2)

使い分け

  • 好みによりますが、column_stack は関数の意図が明確で、c_ はよりコンパクトです。
  • c_column_stack とほぼ同等の機能を提供し、コードの記述をさらに簡潔にできます。

numpy.column_stack() は、特に1次元配列を列として結合したい場合に非常に便利で、直感的です。しかし、以下のような代替手段も存在し、それぞれの状況で最適な選択肢となり得ます。

  • numpy.c_: column_stack とほぼ同等の機能をより簡潔な記法で提供する。
  • numpy.stack(..., axis=1): 新しい軸を作成して結合。すべての入力配列が同じ形状である必要がある。
  • numpy.hstack(): 水平結合。2次元配列では column_stack と同じだが、1次元配列では結果が異なる。
  • numpy.concatenate(..., axis=1): 最も汎用的な結合方法。1次元配列の場合は明示的な整形([:, np.newaxis]など)が必要。