NumPy では、形状の異なる配列同士でも計算ができることがあります。これをブロードキャスティングと呼びます。明示的にループを書かなくても、NumPy が自動的に配列の形状を揃えてくれる仕組みです。
基本的な例
配列とスカラー(単一の数値)の演算は、最も単純なブロードキャスティングです。
import numpy as np a = np.array([1, 2, 3, 4, 5]) print(a * 2) # [ 2 4 6 8 10] print(a + 10) # [11 12 13 14 15]
スカラーが配列の各要素に「放送」されて、同じ形状になったかのように計算されます。
1次元配列と2次元配列
1次元配列と2次元配列の演算でも、ブロードキャスティングが働きます。
a = np.array([[1, 2, 3], [4, 5, 6]]) # 2行3列 b = np.array([10, 20, 30]) # 3要素 print(a + b) # [[11 22 33] # [14 25 36]]
1次元配列 b が各行に「放送」されて、2行3列の配列として扱われます。
ブロードキャスティングのルール
形状が異なる配列で計算するとき、NumPy は以下のルールで形状を揃えます。
ルール1:次元数を揃える
次元数が少ない配列の先頭に1を追加する。例:形状 (3,) は (1, 3) として扱われる
ルール2:サイズ1の次元を拡張
各次元で、サイズが1の方を相手のサイズに合わせる。サイズが1でも異なる場合はエラー
具体的に見てみましょう。
a = np.ones((3, 4)) # 形状 (3, 4) b = np.array([1, 2, 3, 4]) # 形状 (4,) # bは (1, 4) → (3, 4) に拡張される print((a + b).shape) # (3, 4)
列方向のブロードキャスト
列ベクトル(2次元で列が1)を使うと、列方向に放送されます。
a = np.array([[1, 2, 3], [4, 5, 6]]) # 形状 (2, 3) b = np.array([[10], [20]]) # 形状 (2, 1) print(a + b) # [[11 12 13] # [24 25 26]]
reshape(-1, 1) で列ベクトルを作ると便利です。
b = np.array([10, 20]).reshape(-1, 1) print(b.shape) # (2, 1)
ブロードキャストできない例
両方のサイズが1でなく、かつ異なる場合はエラーになります。
a = np.ones((3, 4)) # 形状 (3, 4) b = np.ones((3,)) # 形状 (3,) → (1, 3) # (3, 4) と (1, 3) は列数が4と3で合わない # print(a + b) # ValueError
利点と注意点
利点
ループを書かずに済む。コードが簡潔になり、実行も高速
注意点
意図しないブロードキャストでバグになることも。形状をしっかり把握しておく
ブロードキャスティングを理解すると、NumPy の表現力が大きく広がります。最初は戸惑うかもしれませんが、形状の変化を意識しながら使ってみてください。