NumPyで平均をとる方法としてnp.mean
とnp.average
の2つがある(他にもあるかも知れないが)。ここでは、その二つの違いに関しては他の記事に任せるとして、処理速度としてはどちらが優秀なのかを見ていく。
なお、以下のコードはこのサイトを参考した。
実行環境
CentOS Linux release 7.6.1810 (Core)
Python 3.8.5
実行コード1
まずは単純に1次元の配列を平均する。
import timeit
import numpy as np
def func_average(n):
return np.average(np.arange(n**2))
def func_mean(n):
return np.mean(np.arange(n**2))
n = 1000
loop = 1000
result_average = timeit.timeit(lambda: func_average(n), number=loop)
result_mean = timeit.timeit(lambda: func_mean(n), number=loop)
print('average: ', result_average / loop)
print('mean: ', result_mean / loop)
実行結果
average: 0.0015093836802989244
mean: 0.001964871450792998
この他にも4回計測したが、いずれもnp.average
が20~30%ほど速かった。
実行コード2
次に、2次元配列の平均をとる。
import timeit
import numpy as np
def func_average(n):
return np.average(np.arange(n**2).reshape(n, n))
def func_mean(n):
return np.mean(np.arange(n**2).reshape(n, n))
n = 1000
loop = 1000
result_average = timeit.timeit(lambda: func_average(n), number=loop)
result_mean = timeit.timeit(lambda: func_mean(n), number=loop)
print('average: ', result_average / loop)
print('mean: ', result_mean / loop)
実行結果
average: 0.0016613604403100909
mean: 0.002270303561817855
こちらの場合でも、np.average
が速かった。
考察
他にも似たような条件を試してみたのだが、どうやってもnp.average
の方が計算速度が速いという結果が出た。これはnp.mean
の意味が無いのでは...
さすがにそんなはずはないと思い、さらに検索してみるとこのようなスレッドを発見。以下翻訳、改変して引用:
(上略)
average
とmean
の考慮すべき違いは他にもある(この前のスレッドで違いが他にも述べられている)。average
はmaskを考慮せずに配列の値全部の平均を取るのに対して、mean
はmaskを考慮するため、maskされていない値のみで平均を取る。
g = [1,2,3,55,66,77]
f = np.ma.masked_greater(g,5) # 5より大きい値をマスクする -> [1,2,3,--,--,--]
print(np.average(f)) # 34.0 (= (1+2+3+55+66+77) / 6)
print(np.mean(f)) # 2.0 (= (1+2+3) / 3)
なるほど、欠損値を含む配列を扱う場合はmean
を使うべきであるようである。
結論
- 単純な処理速度だけでいえば
average
。 - 欠損値を含むデータを扱うなどで
numpy.ma
を使う場合は、mean
。
用途に応じて使い分けるのが一番だが、プログラム全体にかかる時間からするとそれに占めるaverage
やmean
の割合は微々たるものであると思うため、何も考えずmean
を使うという選択肢もアリではなかろうか。