python超入門ということで、pythonを使って統計を学習します。
python超入門×統計学超入門の1回目です。
pythonのインストールはこちら
1回目は代表値である平均値・中央値・最頻値をpythonを使って学習します。
※学習用なので、素早く統計を取りたい方は標準ライブラリ「statistics」を使用してください
pyhton側では、randomモジュール・csvモジュール・mathモジュール・関数を使用します。
はじめに
あたりまえですが統計学を取るために、データが必要になります。しかし、全人類の貯蓄など全データを取ることが現実的でない場合は一部のデータを使いますが、これを「 標本 」といいます。英語でいうと馴染みのある「 SAMPLE 」です。一方で全データは「全標本/母集団」(population/universe)といいます。
代表値
統計における超基本の代表値を3つ取り上げます。
- 平均値 … 1データあたりの値(データ合計値÷データ数)
- 中央値 … 全データを小さい順に並べたど真ん中の値
- 最頻値 … 一番登場回数が多い値
基本的に「平均値」があれば良いと思われるかもしれませんが、「平均値」だけではうまくいかない場合が多々あります。それが「異常値」の存在です。
例えば、とある小学校Zの6年2組の生徒が4人いて、A君は500円、B君は750円、Cさんは1000円、大金持ちD君は100,000円を毎月お小遣いをもらっているとしましょう。もし平均値で語ってしまうと、「Z小学校の6年2組の子は平均で25,000円以上もお小遣いをもらってるらしいわよ!」と言われてしまいます。これにはA,B,Cの子たちはたまったものではありません。
ゆえに平均値以外の代表値も必要なのです。
関数
では関数を使って代表値をプログラミングしていきます。
関数はある値を入れると内部で処理を行い、処理結果の値を返す機能で、pythonでは
def 関数名(入力値):
処理内容
return 返却値
と記載します。
次に新規ファイルを作成し、「representativeValue.py」と名前を付けて保存しましょう。
平均値
平均値は全データの合計をデータ数で割った値なので、
def average (datas):
average_value = sum(datas) / len(datas)
return average_value
このように記載します。
※投入する値「datas」はリストを想定
※「average_value」は変数というデータを入れる箱なので、名称は何でもOK
※sumはdatas(入れた値)の総和を計算するデフォルトの関数
※lenはdatas(入れた値)の数を返すデフォルトの関数
ではリスト型のデータを作成し、動かしてみよう
def average (datas):
average_value = sum(datas) / len(datas)
return average_value
datas = [1,2,3,4,5,6,7,8,9]
print(average(datas))
※「datas」という変数に値をリストとして格納
※printは表示させるデフォルト関数
ファイルを保存し、コマンドプロンプトで実行する
python representativeValue.py
5.0と表示されたら成功です!
中央値
中央値は少し複雑です。
上記データのように1~9の値がリストに格納されている場合は、左からも右からも5番目の値である5が中央値ですが、
リストに1~10の値があった場合は、中央値は5と6の間で5.5が正しいです。
ゆえにリスト内のデータ数が偶数の場合と奇数の場合で分けて考える必要があります。
※その前にリストデータの取得方法はdatas[i]と記載しますが、iは0からスタートすることに注意してください。
datas[0] は1、 datas[1] は2 となります。
では先ほどのファイルに追記します
import math
def average (datas):
average_value = sum(datas) / len(datas)
return average_value
def median (datas):
datas_len = len(datas) #データ数
dev_number = datas_len / 2 #データ数の半分(データの中央)
if datas_len % 2 == 0: #データ数を2で割ったときの余りが0の場合(※つまり偶数)
median_value = (datas[int(dev_number)-1] + datas[int(dev_number)]) / 2 #真ん中の2データの合計の平均値
else:
median_value = datas[int(math.floor(dev_number))]
return median_value
※上にimportを追加しました。mathというライブラリを使用するためです。
※math.floorで小数点を切り捨てます
※if文のあとに条件を記載し、次行で1段落つけることで条件文を作成します。( elseも同様 )
※intは整数値に直す関数です。計算をしているので「dev_number」は小数点を含むfloat型になっています。
では偶数と奇数で実行してみましょう
#representativeValue.pyに追記
datas1 = [1,2,3,4,5,6,7,8,9]
datas2 = [1,2,3,4,5,6,7,8,9,10]
print(median(datas1))
print(median(datas2))
5.0と5.5が表示されたら成功です!
最頻値
最頻値は一番出現数の多い数です。
以下の手順で最頻値を求めることにします
- リストを小さい順に並べ替える
- 1つ目の値を変数1,2,3に格納する
- 変数4,5に1の値を入れる
- 変数1に次の値を入れる
- 変数1と変数2を比較し、同様なら変数4の値を1増やす。異なる場合は変数4>変数5なら変数5に変数4の値を入れ変数3に変数2を入れる。そして変数4に1を入れ、変数2に変数1を入れる。変数4>変数5でない場合は 変数4に1を入れ、変数2に変数1を入れる。
- 4に戻って繰り返し
- 最後のデータが終わったら 変数4>変数5なら変数5に変数4の値を入れ変数3に変数2を入れる。
訳わからないですね。。書いている自分でもわかりません。
つまり変数1が今処理している数字、変数4が処理中の数字の件数、変数3と5が現在最大の数字と件数を格納する箱です。
コードは以下のようにしました。
def mode(datas):
datas.sort()
datas_len = len(datas)
data1 = data2 = data3 = datas[0] #1番目のリストデータを変数1,2,3に代入
cnt1 = cnt2 = 1
for i in range(1,datas_len-1): #リストの1(2番目データ)~最後までループ
data1 = datas[i]
if data1 == data2:
cnt1 = cnt1 + 1
else:
if cnt1 > cnt2 :
cnt2 = cnt1
data3 = data2
data2 = data1
cnt1 = 1
if cnt1 > cnt2 :
cnt2 = cnt1
data3 = data2
return str(data3) + 'が' + str(cnt2) + '回'
datas1 = [1,2,3,2,5,2,3,4,1]
datas2 = [1,2,3,2,5,3,1,3,2,2]
print(mode(datas1))
print(mode(datas2))
※for i in range(num1 ,num2)でnum1からnum2までループする構文になります。1回目は1という数字が「i」にはいります。
最頻値の取得ロジックはいろいろあると思いますし、このやり方は自分でもスマートではないと思うので、どのやり方が一番良いか試してみると面白いかもしれません。
あともう1つ、上記手法だと最頻値が複数同順位の場合、最小値が優先して出力されるようになっています。cnt1>cnt2の箇所です。標準ライブラリだと複数最頻値がある場合はエラーになったかと思います。
テストデータを作成
これまでは手動でリストデータを作成しましたが、実際は外部からデータをダウンロードして分析することが多いと思います。
また、サンプルデータを作成するのも面倒なので、プログラムから作成します。
ランダム値のcsvファイルを生成
今回は30人のクラスの総合評価1~5段階とみなしてデータをランダムに作成してみます。
import random
filename = 'sampledata.csv'
text = ''
for i in range(0,29):
text += str(random.randint(1,5))
with open(filename,'w') as f:
f.write(','.join(text))
※ランダムの数値を扱う標準モジュールをインポートします
※for文で30回ループしrandint関数で1~5の数字をランダム生成し、「text」リストに入れています
※openモジュールでファイルを書き込みように開き、TEXTリストをjoin関数で’,’区切りで連結しています。
実行するとソースコードと同じフォルダ内に「sampledata.csv」が出来ます
csvファイルを取り込む
出力したcsvを取り込むにはcsvモジュールを使用します
import csv
filename = 'sampledata.csv'
with open(filename) as f:
r = csv.reader(f, delimiter=',')
for l in r:
print(l)
このプログラムを実行すると1行ずつリストとして出力されます。今回のデータは1行しかないですが、csvデータは行*列があるので二重リストとして変数に入れます。
import csv
filename = 'sampledata.csv'
with open(filename) as f:
r = csv.reader(f, delimiter=',')
rows = [[ll for ll in l] for l in r]
print(rows)
現在取り込んだデータは2重リストかつ文字列型になっているので、内部データをint型にし、実際に使用する1行目のみを取得します。
import csv
filename = 'sampledata.csv'
with open(filename) as f:
r = csv.reader(f, delimiter=',')
rows = [[int(ll) for ll in l] for l in r]
print(rows[0])
これが実際に使用するデータとなります
取り込んだcsvファイルの代表値を取得する
最後にデータ取り込みプログラムから代表値取得の関数を呼び出して今回は終了です。
最頻値のところでリストをソートしましたが、呼び出しプログラム側でソートしたするのが〇でしょう。
import csv
import representativeValue as rv #representativeValue.pyをrnという名前で読み込む .pyは不要
filename = 'sampledata.csv'
with open(filename) as f:
r = csv.reader(f, delimiter=',')
rows = [[int(ll) for ll in l] for l in r]
row = rows[0]
print('取り込んだデータ:'+str(row))
row.sort()
print('ソート後のデータ:'+str(row))
print('平均値:'+str(rv.average(row)))
print('中央値:'+str(rv.median(row)))
print('最頻値:'+str(rv.mode(row)))
正しく結果が表示されたでしょうか?
されていれば大成功です!
今回はpythonを使って統計学の基本の代表値を扱いました。実際には、今回の代表値の関数は作成せずとも、statisticsやnumpyというライブラリで用意されていますが、pyhtonを含めた基本学習ということで作成しました。
次回はその他代表値や基本値、視覚的な図形を扱っていこうと思います。
コメント
[…] 前回は、基本的な代表値である平均値・中央値・最頻値を学び、取得プログラムを作り、csvモジュールで作成しました […]
[…] 前回は、基本的な代表値である平均値・中央値・最頻値を学び、取得プログラムを作り、csvモジュールで作成しました […]
[…] 前回記事で説明した通り、異常値の存在で、1つの代表値では都合の悪いことが多いです。 […]
[…] 次回は1回目から今回の成果を集結して統計を取ってみましょう […]