第8回「NumPyによるデータ分析(4)」

こんにちは、小澤です。

前回は、NumPyの応用機能として、サンプル配列を用いた関数について学びました。今回も引き続き、NumPyの応用機能について学んでいきましょう。教科書『Pythonによる新しいデータ分析の教科書(第2版)』の4.1.3章「NumPyの各機能」ではブロードキャストと配列の掛け算の部分(124ページ〜129ページ)です。

ブロードキャスト

NumPyのブロードキャストは、異なる形状の配列間で算術演算を行う際に、自動的に次元を調整する機能です。これにより、配列のサイズが異なる場合でも、明示的な次元の調整なしに演算を行うことが可能になります。ブロードキャストは、ユニバーサルファンクションと同じく、NumPyにとって非常に強力な機能です。

まず、ブロードキャストのルールについて整理しておきましょう。

  1. 次元の数が異なる場合:次元の数が少ない配列の形状の先頭に1を追加して、両方の配列の次元数を揃えます。
  2. 特定の次元のサイズが1の場合:その次元に沿って、大きいサイズに合わせて要素をコピーします。
  3. いずれの次元のサイズも互いに一致するか、どちらかが1である場合:ブロードキャストが可能です。
  4. 上記の条件を満たさない場合:ブロードキャストは不可能であり、エラーが発生します。

スカラーと配列の四則演算

スカラー(単一の数値データ)と配列を四則演算する場合、スカラーは配列の各要素に加算されます。なお、NumPyをインポートしますが、ここではnpと別名定義しています。

import numpy as np

# 配列の定義
a = np.array([10, 20, 30])

# スカラーとの加算
a + 5
# array([15, 25, 35])

# スカラーから配列の各要素を引く
5 – a
# array([ -5, -15, -25])

# スカラーとの掛け算
a * 2
# array([20, 40, 60])

# スカラーのべき乗
a ** 2
# array([100, 400, 900])

# スカラーで割る
a / 10
# array([1., 2., 3.])

# 割り切れない場合
a / 3
# array([ 3.33333333,  6.66666667, 10.        ])

# ゼロで除算した場合
a / 0
# array([inf, inf, inf])

# 1e-10(10の-10乗)という非常に小さな数値で除算した場合
a / (1e-10)
# array([[1.e+10, 2.e+10, 3.e+10],
#        [4.e+10, 5.e+10, 6.e+10]])

ちなみに、ブロードキャストを使わずにNumPy配列の各要素にスカラーを加える方法は以下のようになります。少々冗長になるかもしれません。

[x + 5 for x in a]
# [15, 25, 35]

異なるサイズの配列の足し算

次元が異なる2つの配列を加算する場合は、ブロードキャストによって自動的に形状が調整されます。

この例では、配列aは形状は (3, 1) 、配列 bは形状 (1, 3) です。ブロードキャストにより、aは各列にbの要素が加算される形で形状 (3, 3) に拡張され、bも同様に各行にaの要素が加算される形で形状 (3, 3) に拡張されます。結果として得られる配列は以下のようになります。

import numpy as np

# 配列の定義
a = np.array([10, 20, 30])
# [10 20 30]

# 形状が(3, 1)の配列
b = np.array([[1], [2], [3]])
# [[1]
#  [2]
#  [3]]

# 配列の足し算
a + b
# array([[11, 21, 31],
#        [12, 22, 32],
#        [13, 23, 33]])

# 引き算
a – b
# array([[ 9, 19, 29],
#        [ 8, 18, 28],
#        [ 7, 17, 27]])

# 掛け算
a * b
# array([[10, 20, 30],
#        [20, 40, 60],
#        [30, 60, 90]])

# 割り算
a / b
# array([[10.        , 20.        , 30.        ],
#        [ 5.        , 10.        , 15.        ],
#        [ 3.33333333,  6.66666667, 10.        ]])

配列の掛け算

NumPyで配列の掛け算を行う方法には、要素ごとの掛け算と行列積(ドット積)の2種類があります。これらは異なる計算を行うため、使用する状況に応じて適切な方を選択する必要があります。

要素ごとの掛け算

要素ごとの掛け算は、2つの配列の対応する要素同士を掛け合わせるものです。この操作には、*演算子またはnp.multiply()関数を使用します。配列の形状が異なる場合、ここでもブロードキャストのルールに従って形状が調整されます。

import numpy as np

# 配列を定義
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 要素ごとの掛け算
result = a * b
# または
result = np.multiply(a, b)

print(result)
# [ 4 10 18]

行列積

行列積は、線形代数における行列の掛け算です。教科書で紹介しているのは、こちらの行列積です。2つの配列の行列積を計算するには、np.dot()関数、np.matmul()関数、または、@演算子を使用します。行列積を計算するためには、最初の配列の列数と2番目の配列の行数が一致している必要があります。

import numpy as np

# 2×3行列
a = np.array([[1, 2, 3],
              [4, 5, 6]])
# 3×2行列
b = np.array([[7, 8],
              [9, 10],
              [11, 12]])

# 行列積
result = np.dot(a, b)
# または
result = a @ b
# または
result = np.matmul(a, b)

print(result)
# [[ 58  64]
#  [139 154]]

まとめ

今回は、NumPyの配列操作におけるブロードキャストと掛け算を紹介しました。これらの機能は、さまざまな数値計算を効率的に行うために使用されますので、ぜひ理解してください。

次回も引き続き、NumPyの応用機能について説明します。真偽値、関数とメソッドを取り上げます。ぜひ次回もお楽しみにしてください。

PAGE TOP