平均と分散の計算スクリプトなど
リストとNumpy配列
Pythonのリストもnumpyの配列(ndarray型:n-dimensional array)も配列を表すが、定義されている演算などに違いがある。例えば、足し算+はリストでは連結であるが、ndarrayでは項目(要素)ごとの足し算である。例えば、リストの足し算は
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> a + b
[1, 2, 3, 4, 5, 6]
となり、ndarrayの足し算は
>>> import numpy
>>> a = numpy.array([1, 2,
3])
>>> b = numpy.array([4, 5,
6])
>>> a + b
array([5, 7, 9])
となる。関数numpy.arrayは、リストからndarray型のオブジェクトを生成する関数である。
リストで項目ごとの和をとることは、例えば、リスト コンプリヘンション(list comprehension)を用いて
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> [x + y for x, y in zip(a,
b)]
[5, 7, 9]
とできる。
List comprehensionとは、角括弧[と]で囲まれた次の形式のものでリストを表す。
[式 for 文]
for文の実行で計算された式の値がリストの要素(項目)となる。例えば、
>>> ['例' for i in range(3)]
['例', '例', '例']
である。上の例では、変数iの値に関わらず式の値は’例’である。
ndarrayの連結をlist comprehensionを用いて行うと
>>> import numpy
>>> a = numpy.array([1, 2,
3])
>>> b = numpy.array([4, 5,
6])
>>> numpy.array([x for x in
a] + [y for y in b])
array([1, 2, 3, 4, 5, 6])
となる。
リストに自然数を掛けると連結になる。例えば、
>>> [1, 2, 3] * 2
[1, 2, 3, 1, 2, 3]
である。ndarrayに自然数を掛けると、各要素が自然数倍される。例えば、
>>> import numpy
>>> numpy.array([1, 2, 3]) *
2
array([2, 4, 6])
である。
ndarrayのべき乗は、各要素がべき乗される。例えば、
>>> import numpy
>>> numpy.array([1, 2, 3]) **
2
array([1, 4, 9], dtype=int32)
である。
リストの項目和と平均値はfor文を用いると次のように求められる。
>>> data = [1, 2, 3]
>>> v = 0
>>> for x in data:
v
+= x
>>> print('和 = ', v)
和 = 6
>>> print('平均 = ', v / len(data))
平均 = 2.0
和を求める関数sumを用いれば、以下のようになる。
>>> data = [1, 2, 3]
>>> print('和 = ', sum(data))
和 = 6
>>> print('平均 = ', sum(data) / len(data))
平均 = 2.0
ndarrayの場合のfor文を用いたスクリプトは、
>>> import numpy
>>> data = numpy.array([1, 2,
3])
>>> v = 0
>>> for x in data:
v
+= x
>>> print('和 = ', v)
和 = 6
と書けるが、numpyの和を求める関数sumと平均値を求める関数meanを用いると以下のようになる。
>>> import numpy
>>> data = numpy.array([1, 2,
3])
>>> print('和 = ', data.sum())
和 = 6
>>> print('平均 = ', data.mean())
平均 = 2.0
リストのデータの分散をfor文で求めるスクリプトは次のようになる。
>>> data = [1, 2, 3]
>>> u = 0.0
>>> for x in data:
u
+= x
>>> m = u / len(data)
>>> t = 0.0
>>> for x in data:
t
+= (x - m) ** 2
>>> v = t / len(data)
>>> print('分散 = ', v)
分散 = 0.6666666666666666
Numpyのndarray型のデータは次のように分散を求めることができる。
>>> import numpy
>>> data = numpy.array([1, 2,
3])
>>> m = data.sum() /
len(data)
>>> v = ((data - m) **
2).sum() / len(data)
>>> print('分散 = ', v)
分散 = 0.6666666666666666
Numpyの分散を求める関数varを用いると
>>> import numpy
>>> data = numpy.array([1, 2,
3])
>>> print('分散 = ', data.var())
分散 = 0.6666666666666666
である。
Pythonでは、いろいろなプログラミングを楽しむことができる。
行列演算などを扱った拙著
岡本安晴「いまさら聞けないPythonでデータ分析」、丸善出版
を用意している。参考になれば幸いである。
まお、大きなデータを扱う場合は処理速度が問題になるが、和を関数numpy.sumで求める場合とfor文で1つずつ足す場合を比較するスクリプトを以下のように作成してみた。
import time
import numpy
from numpy.random import rand
n = 10000000
v = rand(n)
t0 = time.monotonic()
v_sum = v.sum()
t1 = time.monotonic()
print('{0:.3f}sec
/numpy.sum()'.format(t1 - t0))
t0 = time.monotonic()
v_sum = 0.0
for s in v:
v_sum += s
t1 = time.monotonic()
print('{0:.3f}sec /for
sentence'.format(t1 - t0))
実行結果例は以下のようである。
0.015sec /numpy.sum()
3.078sec /for sentence