『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

データの平均値

算術平均と加重平均

データ $X=[x_1,\ x_2,\ \cdots\ x_N]$ の 算術平均 (arithmetic mean)
 \[\frac{x_1+x_2+\ \cdots\ x_N}{N}=\frac{\displaystyle\sum_{k=1}^{N}x_k}{N}\]
によって定義されます。また、$X$ の各要素に
 \[W=[w_1,\ w_2,\ \cdots\ w_N]\]
の重みを乗じて総和をとって、$W$ の合計で割った値
 \[\frac{w_1x_1+w_2x_2+\ \cdots\ w_Nx_N}{w_1+w_2+\ \cdots\ +w_N}=\frac{\displaystyle\sum_{k=1}^{N}w_kx_k}{\displaystyle\sum_{k=1}^{N}w_k}\]
加重平均 (weighted average) といいます。

statistics.mean()

statistics.mean() はイテラブルオブジェクトの算術平均を計算します。

# PYTHON_STATISTICS_MEAN

# In[1]

import statistics as st

x = [10, 20, 30]

# xの算術平均を計算
x_mean = st.mean(x)

print(x_mean)
# 20

fraction.Fraction クラスのオブジェクト(分数)の平均を計算することもできます。

# In[2]

# fractionsモジュールから分数クラスをインポート
from fractions import Fraction as F

# x=[1/3, 2/5, 2/7]
x = [F(1, 3), F(2, 5), F(2, 7)]

# xの算術平均を計算
x_mean = st.mean(x)

print(x_mean)
# 107/315

decimal.Decimal クラスのオブジェクト(十進浮動小数点数)の平均値を求めることもできます。

# In[3]

# decimalモジュールから十進浮動小数点数クラスをインポート
from decimal import Decimal as D

x = [D('4.50'), D('0.71'), D('3.28')]

# xの算術平均を計算
x_mean = st.mean(x)

print(x_mean)
# 2.83

numpy.mean()

サードパーティー製パッケージ NumPy を活用すれば、大規模なデータの平均値を高速計算することができます。numpy.mean() は受け取った配列の 算術平均 を返します。

# NUMPY_MEAN

# In[1]

import numpy as np

x = np.array([10, 20, 30, 40, 50])

# 配列xの平均値を計算
x_mean = np.mean(x)

print(x_mean)
# 30.0

オプション引数 dtype で戻り値のデータ型を指定することができます。

# In[2]

x = np.array([10, 20, 30, 40, 50])

# 配列xの平均値を計算(戻り値は32バイト整数)
x_mean = np.mean(x, dtype = np.int32)

print(x_mean)
# 30

オプション引数 axis によって平均をとる軸を指定することができます。たとえば 2次元配列であれば、axis = 0 は列方向、axis = 1 は行方向に沿って平均値を計算します。

# In[3]

x = np.array([[10, 100, 1000],
              [20, 200, 2000],
              [30, 300, 3000]])

# 0軸(列)方向に平均値を計算して1次元配列に格納
xm_0 = np.mean(x, axis=0)

# 1軸(行)方向に平均値を計算して1次元配列に格納
xm_1 = np.mean(x, axis=1)

print(xm_0)
print(xm_1)

# [  20.  200. 2000.]
# [ 370.  740. 1110.]

numpy.average()

numpy.average() は受け取った配列の 算術平均 を返します。この関数は numpy.mean() とよく似た機能をもちます。実際、オプション引数を何も指定しなければ、実行結果は numpy.mean() と全く同じです。

# NUMPY_AVERAGE

# In[1]

import numpy as np

x = np.array([10, 20, 30, 40, 50])

# xの算術平均
x_av = np.average(x)

print(x_av)
# 30.0

軸に沿った平均値も numpy.mean() と同じように計算できます。
ただし、numpy.average() ではデータ型を指定することはできません。
オプション引数 weights によって、渡した配列の各要素に重みをつけた加重平均を計算することができます。

# In[2]

x = np.array([30, 20, 10])

# 重みを設定
w = np.array([1, 2, 3])

# 加重平均(1*30+2*20+3*10)/(1+2+3)=100/6を計算
x_av = np.average(x, weights=w)

print(x_av)
# 16.666666666666668

特定の軸に沿って加重平均を計算することもできます。

# In[3]

# 3×2の配列x
# [[0 1]
#  [2 3]
#  [4 5]]
x = np.arange(6).reshape((3,2))

# 第1列に重み2, 第2列に重み3をつけて加重平均を計算
x_av = np.average(x, axis=1, weights=[2, 3])

print(x_av)
# [0.6 2.6 4.6]

デフォルトで False に設定されている returned に True を渡すと、加重平均と重みの合計がタプル形式で返ります。

# In[4]

x = np.array([10, 100, 1000])

# 重みを設定
w = np.array([3, 2, 1])

# 加重平均と重みの合計を取得
x_av = np.average(x, weights=w, returned=True)

print(x_av)
# (205.0, 6.0)

調和平均

$N$ 個のデータ $X=[x_1,\ x_2,\ \cdots\ x_N]$ について、$N$ を個々の値 $x_i$ の逆数平均で割った値
 \[\frac{N}{\cfrac{1}{x_1}+\cfrac{1}{x_2}+\ \cdots\ +\cfrac{1}{x_N}}=\frac{N}{\displaystyle \sum_{i=1}^{N}(1/x_i)}\]
調和平均(harmonic mean)とよびます。たとえば車に乗って、$2$ km の道のりを最初の $1$ km は時速 $40$ km で、後半の $1$ km は時速 $60$ km で走行したとき、それぞれの区間を移動するのに要した時間は $1/40$ h, $1/60$ h となります。したがって、全区間を移動するために必要な時間は
 \[t=\frac{1}{40}+\frac{1}{60}\]
となり、この区間を走った平均速度は
 \[v=\frac{2}{t}=\frac{2}{\cfrac{1}{40}+\cfrac{1}{60}}\]
で与えられます。

statistics.harmonic_mean()

statistics.harmonic_mean() はデータの調和平均を返します。たとえば、40 と 60 の調和平均は次のように計算します。

# PYTHON_STATISTICS_HARMONIC_MEAN

# In[1]

from statistics import harmonic_mean

x = [40, 60]

# xの調和平均を計算
x_hm = harmonic_mean(x)

print(x_hm)48.0

scipy.stats.hmean()

大規模なデータの調和平均を計算する場合は Scipyパッケージをインポートすることをおすすめします。scipy.stats.hmean() は配列の調和平均を返します。たとえば、第1引数に 2次元配列を受け取った場合、オプション引数 axis に何も指定しなければ、列ごとに調和平均を計算して 1次元配列に格納します。

# SCIPY_STATS_HARMONIC_MEAN

# In[1]

import numpy as np
from scipy.stats import hmean

x = np.array([[10, 20, 30],
              [40, 50, 60],
              [70, 80, 90]])

# 第0軸に沿って調和平均を計算
x_hm = hmean(x)

print(x_hm)
# [21.53846154 36.36363636 49.09090909]

これは axis = 0 を指定した場合と同じ結果です。
行ごとに調和平均を計算したいときは axis に 1 を渡します。

# In[2]

x = np.array([[10, 20, 30],
              [40, 50, 60],
              [70, 80, 90]])

# 第1軸に沿って調和平均を計算
x_hm = hmean(x, axis=1)

print(x_hm)
# [16.36363636 48.64864865 79.16230366]

幾何平均(相乗平均)

$X=[x_1,\ x_2,\ \cdots\ x_N]$ の 幾何平均 (geometric mean)
 \[(x_{1}\: x_{2}\: \cdots\: x_{N})^{\frac{1}{n}}=\left(\prod_{k=1}^{N}x_k\right)^{\frac{1}{n}}\]
によって定義されます。

scipy.stats.mstats.gmean()

SciPy がインストールされていれば、scipy.stats.mstats.gmean() を使って幾何平均を求めることができます。

# SCIPY_STATS_GEOMETRIC_MEAN

# In[1]

import numpy as np
from scipy.stats.mstats import gmean

# x=[1,2,3,4,5,6,7,8,9]
x = np.arange(1, 10)

# xの幾何平均を計算
x_gmean = gmean(x)

print(x_gmean)
# 4.147166274396913

オプション引数 axis で平均をとる軸を指定することができます。

# In[2]

# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]
x = np.arange(1, 10).reshape((3, 3))

# 縦軸方向に沿って幾何平均を計算
x_gmean_0 = gmean(x, axis=0)

# 横軸方向に沿って幾何平均を計算
x_gmean_1 = gmean(x, axis=1)

print("0軸方向の平均:{}".format(x_gmean_0))
print("1軸方向の平均:{}".format(x_gmean_1))

# 0軸方向の平均:[3.03658897 4.30886938 5.45136178]
# 1軸方向の平均:[1.81712059 4.93242415 7.95811442]

コメント

  1. HNaito より:

    下記は誤植と思われますので、ご確認ください。

    NUMPY_MEAN-3プログラムの上の文で、
    axis=0 は行方向、axis=1 は列方向 → axis=0 は列方向、axis=1 は行方向

    同じプログラムのコメントで、
    # 0軸 (行) → # 0軸 (列)
    # 1軸 (列) → # 1軸 (行)

    NUMPY_AVERAGE-2 プログラムの上の文の最後で、
    できます。、→ できます。