Pythonプログラミング(ステップ7・リスト・基本的な代表値の計算)

このページでは、基本的な代表値や散布度を計算するアルゴリズムをまとめておく。

以下では、$N$件のデータが配列(リスト)で $$ X = [x_0, x_1, \cdots, x_{N-1}] $$ のように与えられている場合を想定する。添字は0から始まり、$N-1$が末尾。

Pythonコードに翻訳する際には、変数名はわかりやすいものに適宜変更すること(例: $\mu$はmuなど)

アルゴリズムの学習のため、なるべく小さなステップに分解して記述したが、Pythonに標準的に内蔵されている機能を使うことで、 基本的な統計量は簡単に求めることができる。そのやり方については、左側の欄に付記した。 また、リスト(配列)操作については、こちらのページも併せて参照のこと。

平均

PythonのリストXの要素数は

N=len(X)

で得られる。また、Xの総和は、シンプルに

s=sum(X)

で得られる。

平均は最も基本的な代表値である。「総和」のアルゴリズムで総和を求め、それをデータ件数で割ればよい。

平均を求めるアルゴリズム
Input: 配列 $X$
Output: 平均値 $\mu$
1: $N \leftarrow$ データ件数
2: $s \leftarrow 0$
3: $i$ を0から、$N$未満まで、1ずつ増やしながら、5:までを繰り返す:
4:    $s \leftarrow s + x_i$
5: 反復ここまで
6: $\mu \leftarrow s / N$
7: $\mu$を出力

最大値・最小値

PythonのリストXの要素の最大値は

max(X)

で、最小値は

min(X)	

で得られる。

最大値・最小値求めるアルゴリズム
Input: 配列 $X$
Output: 最小値 $min$, 最大値 $max$
01: $N \leftarrow$ データ件数
02: $min \leftarrow x_0$
03: $max \leftarrow x_0$
04: $i$ を1から、$N$未満まで、1ずつ増やしながら、9:までを繰り返す:
05:    もし $x_i \lt min$ ならば:
06:       $min \leftarrow x_i$
07:    もし $x_i \gt max$ ならば:
08:       $max \leftarrow x_i$
09: 反復ここまで
10: $min$, $max$を出力する

中央値(メジアン)

Pythonで整数の除算は // を用いる。

リストXを昇順に並べ替えるには

X.sort()

でよい。降順は

X.sort(reverse=True)

statisticsモジュールを使うことで、リストXのメジアンは

import statistics
...
med=statistics.median(X)

で得られる。

データをまず整列し、データの件数が奇数の場合は、$N/2$番目の要素。 件数が偶数の場合は中央の2つの平均。 アルゴリズム中で、除算 $/$ は整数の除算であることに注意(例:$7/2$は3)。

メジアンを求めるアルゴリズム
Input: 配列 $X$
Output: メジアン $m$
1: $N \leftarrow$ データ件数
2: $X$の要素を小さい順に並べ替える
3: もし $N$ が奇数ならば:
4:    $m \leftarrow x_{N/2}$
5: そうでなければ:
6:    $m \leftarrow \frac{x_{(N/2)-1} + x_{N/2}}{2}$
7: $m$を出力

四分位数

まずメジアンを求め、第2四分位数とする。 次に、メジアンより小さい (メジアンは含まない)データと、メジアンより大きい(メジアンは含まない)データそれぞれについてのメジアンを求め、第1、第3四分位数とする。

四分位数を求めるアルゴリズム
Input: 配列 $X$
Output: 第1, 第2, 第3四分位数 $q_1, q_2, q_3$
01: $N \leftarrow$ データ件数
02: $X$の要素を小さい順に並べ替える
03: もし $N$ が奇数ならば:
04:    $q_2 \leftarrow x_{N/2}$
05:    $q_1 \leftarrow$ ( $x_0,\cdots,x_{(N/2)-1}$のメジアン)
06:    $q_3 \leftarrow$ ( $x_{(N/2)+1},\cdots,x_{N-1}$のメジアン)
07: そうでなければ:
08:    $q_2 \leftarrow \frac{x_{(N/2)-1} + x_{N/2}}{2}$
09:    $q_1 \leftarrow$ ( $x_0,\cdots,x_{(N/2)-1}$のメジアン)
10:    $q_3 \leftarrow$ ( $x_{N/2},\cdots,x_{N-1}$のメジアン)
11: $q_1, q_2, q_3$を出力

最頻値(モード)

statisticsモジュールを使うことで、リストXのモードは

import statistics
...
mod=statistics.mode(X)

で得られる。

以下のアルゴリズムでは、まず配列を昇順並べ替え、連続して同じ値が出現する回数をカウントしながら、出現回数が最大の値を求めている。

モードを求めるアルゴリズム
Input: 配列 $X$
Output: モード $m$
01: $N \leftarrow$ データ件数
02: $X$の要素を小さい順に並べ替える
03: $c \leftarrow 0$, $c_{max} \leftarrow x_0$
04: $i$ を1から、$N$未満まで、1ずつ増やしながら、11:までを繰り返す:
05:    もし $x_{i-1} = x_i$ ならば:
06:        $c \leftarrow c + 1$
07:    そうでなければ:
08:        もし $c \gt c_{max}$ ならば:
09:            $c_{max} \leftarrow c$
10:            $mode \leftarrow x_{i-1}$
11: 繰り返しここまで
12: $mode$を出力

標本分散

statisticsモジュールを使うことで、リストXの標本分散は

import statistics
...
v=statistics.variance(X)

で得られる。

分散は最も基本的な散布度である。分散の平方根が標準偏差。

分散を求めるアルゴリズム
Input: 配列 $X$
Output: 分散 $v$
01: $N \leftarrow$ データ件数
02: $s \leftarrow 0$, $q \leftarrow 0$
03: $i$ を0から、$N$未満まで、1ずつ増やしながら、6:までを繰り返す:
04:    $s \leftarrow s + x_i$
05:    $q \leftarrow q + {x_i}^2$
06: 反復ここまで
07: $\mu \leftarrow s / N$
08: $w \leftarrow q / N$
09: $v \leftarrow w - \mu^2$
10: $v$を出力

リストの要素それぞれに、ある演算を施したいケースはよくある。 例えば、リストXの二乗和は、要素をそれぞれ二乗したリストを作成し、そちらのリストの総和を求めればよい。 ラムダ式による無名関数と、map( )関数を組み合わせると、これらのステップは

X2 = list( map(lambda x:x**2, X) )
sum2 = sum(X2)

と記述できる。map(関数,リスト)は、リストの要素それぞれの関数を作用させ、新しいリスト型のオブジェクトを生成する。 そして、list( )で、それを通常のリストに変換する。

lambda:変数名:式 は、変数をコロン(:)の右側に記述した式に変換するような「無名関数」。

この記法を用いると、例えば、リストX の不偏分散は

N=len(X)
mu=sum(X)/N
u2 = sum(map(lambda x:(x-mu)**2, X))/(N-1)

で求められる。