Home

Python統計プログラミング

平均・分散・相関係数・グラフ描画(ヒストグラム、散布図)

 

簡単な統計量とグラフ描画のプログラムをPythonで作ってみた。1変量および2変量の記述統計量グラフ描画ファイル入出力の3セッションに分けて説明する。他の統計分析プログラム例は別のサイトに用意している。

なお、グラフにおける日本語表記については、モジュールjapanize_matplotlibによる場合japanize_matplotlib用いない場合について例を上げた。

統計についての解説は、岡本安晴「データを使いこなすための統計入門」を参照されたい。Pythonのインストールについては、このウェブサイトで説明している。

Pythonによるデータ分析の解説書として

岡本安晴(著)「いまさら聞けないPythonでデータ分析―多変量解析,ベイズ統計分析(PyStan,PyMC)―」丸善出版

を用意した。

なお、本ウェブサイトのプログラム例は圧縮ファイルSmplStatPy.zipにまとめたが、ダウンロード・展開して、自由に御利用下さい。

                                                     

記述統計量

 

1変量の場合

表1の50個の値の平均値と分散などを求めてみる。

表1 50個のスコア

66, 59, 62, 64, 63,68, 65, 59, 68, 64,

65, 51, 67, 64, 83,59, 61, 62, 57, 72,

65, 64, 54, 60, 53,65, 67, 60, 53, 79,

74, 53, 61, 68, 75,50, 57, 55, 66, 56,

55, 61, 70, 71, 49,69, 70, 80, 73, 72

プログラムStatOneVar.pyを以下のように作成した。

============  StatOneVar.py  ==================

 

import math

 

def sqr(x):

    return x * x

 

data = [66, 59, 62, 64, 63,

        68, 65, 59, 68, 64,

        65, 51, 67, 64, 83,

        59, 61, 62, 57, 72,

        65, 64, 54, 60, 53,

        65, 67, 60, 53, 79,

        74, 53, 61, 68, 75,

        50, 57, 55, 66, 56,

        55, 61, 70, 71, 49,

        69, 70, 80, 73, 72]

 

n = len(data)       #   The number of scores

print("n =%d"%n)

 

print("Data...")

i = 1

for x in data:

    print("%5d:"%i + "  %f"%x)

    i+=1

 

sum = 0.0

for x in data:

    sum += x

mean = sum / n

print("Mean = %f"%mean)

ssum = 0.0

for x in data:

    ssum += sqr(x - mean)

var = ssum / n

sd = math.sqrt(var)

print("Variance = %f"%var + "     sd = %f"%sd)

uvar = ssum / (n - 1.0)

sd_uvar = math.sqrt(uvar)

print("Unbiased Var. = %f"%uvar + "     sd(uvar) = %f"%sd_uvar)

=======================================

 

表1のデータをリストdataとして設定(assignment記号 = の働きについては、本節末に補足説明を用意した。)している。平均値、分散、不偏分散、および分散あるいは不偏分散の平方根としての標準偏差が算出されている。それぞれは、次式

で算出される。

プログラムStatOneVar.pyを実行すると、図1のような結果になる。

図1

 

2変量の場合

体重と身長のように2つの変量がペアになっている場合について考える。

表2 [体重, 身長]の50人分のデータ

[70, 168], [68, 165], [62, 159], [56, 156], [70, 170],

[64, 162], [59, 162], [70, 169], [68, 168], [69, 170],

[67, 168], [63, 166], [58, 163], [74, 170], [65, 168],

[60, 160], [65, 165], [72, 175], [61, 164], [77, 174],

[68, 164], [64, 161], [70, 166], [47, 147], [66, 165],

[68, 170], [73, 174], [74, 172], [63, 164], [83, 182],

[58, 159], [64, 166], [67, 167], [75, 174], [67, 163],

[68, 166], [68, 167], [66, 165], [63, 165], [55, 154],

[61, 163], [60, 160], [62, 164], [62, 160], [59, 160],

[51, 155], [59, 163], [68, 170], [56, 157], [79, 180]

 

プログラムStatTwoVars.pyでは、表2のデータがリストpairsとして設定されている。

=============  StatTwoVars.py  =================

import math

 

def sqr(x):

    return x * x

 

pairs = [[70, 168], [68, 165], [62, 159], [56, 156], [70, 170],

         [64, 162], [59, 162], [70, 169], [68, 168], [69, 170],

         [67, 168], [63, 166], [58, 163], [74, 170], [65, 168],

         [60, 160], [65, 165], [72, 175], [61, 164], [77, 174],

         [68, 164], [64, 161], [70, 166], [47, 147], [66, 165],

         [68, 170], [73, 174], [74, 172], [63, 164], [83, 182],

         [58, 159], [64, 166], [67, 167], [75, 174], [67, 163],

         [68, 166], [68, 167], [66, 165], [63, 165], [55, 154],

         [61, 163], [60, 160], [62, 164], [62, 160], [59, 160],

         [51, 155], [59, 163], [68, 170], [56, 157], [79, 180]]

 

n = len(pairs)

print("n = %d"%n)

 

sum_x = 0.0

sum_y = 0.0

for i in range(0, n):

    sum_x += pairs[i][0]

    sum_y += pairs[i][1]

mean_x = sum_x / n

mean_y = sum_y / n

print("Mean_x = %f"%mean_x)

print("Mean_y = %f"%mean_y)

ssum_x = 0.0

ssum_y = 0.0

sum_xy = 0.0

for i in range(0, n):

    ssum_x += sqr(pairs[i][0] - mean_x)

    ssum_y += sqr(pairs[i][1] - mean_y)

    sum_xy += (pairs[i][0] - mean_x) * (pairs[i][1] - mean_y)

 

var_x = ssum_x / n

var_y = ssum_y / n

print("Var_x = %f"%var_x)

print("Var_y = %f"%var_y)

sd_x = math.sqrt(var_x)

sd_y = math.sqrt(var_y)

print("sd_x = %f"%sd_x)

print("sd_y = %f"%sd_y)

cor = sum_xy / math.sqrt(ssum_x * ssum_y)

print("r = %f"%cor)

======================================

 

2変量の関係を表すものとして相関係数(correlation coefficient)が求められている。これは、次式

によって算出されている。

プログラムStatTwoVars.pyを実行すると図2のような結果になる。

図2

 

図2の結果は、Windowsのコンソール(端末)での実行結果であるが、図1のようにPythonIDLE上で実行することもできる。

 

 

補足説明:Assignment = について

 

Assignment = については、以下のコードに示されるような注意が必要である。

 

================================

a = [1, 2]

b = a               #   Check-11

b[0] = 3            #   Check-12

print("Check-1")

print(a)

print(b)

 

a1 = [1, 2]

b1 = a1             #   Check-21

a1[0] = 5           #   Check-22

print("Check-2")

print(b1)

print(a1)

 

a2 = [1, 2]

b2 = a2             #   Check-31

b2 = [6, 7]         #   Check-32

print("Check-3")

print(a2)

print(b2)

 

a3 = 10

b3 = a3

b3 = 15

print("Check-4")

print(a3)

print(b3)

================================

 

上のコードを実行すると以下の結果を得る。

 

=================================

Check-1

[3, 2]

[3, 2]

Check-2

[5, 2]

[5, 2]

Check-3

[1, 2]

[6, 7]

Check-4

10

15

=================================

 

Check-1」に続く出力では、同じ出力「[3, 2]」が得られている。これは、Check-11における代入文によって、変数bが変数aと同じものを指し示すものとなっていることを意味している。

Check-2」に続く出力も、代入がb1ではなくa1b1 = a1の右辺)の要素に行われているが、2つの変数b1a1が同じものを表していることを意味していることは変数abの場合と同様であることを意味するものである。

Check-3」に続く出力では、変数b2の値の変更は変数a2には及んでいない。これは、変数の値全体を変更する場合は、変数は新しい変更値を指し示すものとして設定され、それまでの同じものを指し示していた変数a2から切り離されたことを意味している。

Check-4」に続く出力は整数の場合を扱っているが、整数はそれ1つで変数の表す値全体であるので、変数b3に値を設定すると、それまで同じものを表していた変数a3とは別のものを指し示すことになる。

 

 

 

 

グラフ描画

上の表1のデータに対して、ヒストグラムを描くプログラムHistogram_1.pyを作成してみた。描画プログラムではパッケージmatplotlibを用いている(importしている)が、これはPythonに追加インストールするものである。追加インストールの方法は<別のウェブサイト>で説明している。

 

===============  Histogram_1.py  ===============

import matplotlib.pyplot as mpt

import math

 

def sqr(x):

    return x * x

 

data = [66, 59, 62, 64, 63,

        68, 65, 59, 68, 64,

        65, 51, 67, 64, 83,

        59, 61, 62, 57, 72,

        65, 64, 54, 60, 53,

        65, 67, 60, 53, 79,

        74, 53, 61, 68, 75,

        50, 57, 55, 66, 56,

        55, 61, 70, 71, 49,

        69, 70, 80, 73, 72]

 

n = len(data)           #  The number of scores

print("n =%d"%n)

 

print("Data...")

i = 1

for x in data:

    print("%5d:"%i + "  %f"%x)

    i+=1

 

mpt.title("Histogram")      #   The title of the histogram

mpt.xlabel("Score")        #   The label of the x-axis

mpt.ylabel("Frequency")   #   The label of the y-axis

mpt.hist(data, bins = 10)   #   Making the histogram

mpt.show()                  #   Show the histogram

=======================================

 

モジュールmatplotlibを用いているが、これはコンソール(図2に示されているようなWindow)において

pip install matplotlib

とコマンドpipを実行してインストールした。

ヒストグラムの描画は、最後の次のコード

mpt.title("Histogram")      #   The title of the histogram

mpt.xlabel("Score")        #   The label of the x-axis

mpt.ylabel("Frequency")   #   The label of the y-axis

mpt.hist(data, bins = 10)   #   Making the histogram

mpt.show()                  #   Show the histogram

によって行っている。show()の実行によって図3のヒストグラムが表示される。なお、グラフの日本語表記については、本ウェブサイトの後半で説明している。

図3

 

下のフロッピーディスクのアイコンのボタンをクリックすると、表示画像を保存することができる。右上のX印のクリックで、表示画面は閉じられ、show()の実行終了となる。

 

図3のヒストグラムは、枠との関係を調整した方が良さそうである。この調整機能を付け加えたプログラムHistogram_2.pyを以下のように作成してみた、

 

================  Histogram_2.py  =============================

import matplotlib.pyplot as mpt

import math

 

def sqr(x):

    return x * x

 

 

data = [66, 59, 62, 64, 63,

        68, 65, 59, 68, 64,

        65, 51, 67, 64, 83,

        59, 61, 62, 57, 72,

        65, 64, 54, 60, 53,

        65, 67, 60, 53, 79,

        74, 53, 61, 68, 75,

        50, 57, 55, 66, 56,

        55, 61, 70, 71, 49,

        69, 70, 80, 73, 72]

 

n = len(data)           #   The number of scores

print("n =%d"%n)

 

print("Data...")

i = 1

for x in data:

    print("%5d:"%i + "  %f"%x)

    i+=1

 

sum = 0.0

for x in data:

    sum += x

mean = sum / len(data)

print("Mean = %f"%mean)

ssum = 0.0

for x in data:

    ssum += sqr(x - mean)

var = ssum / len(data)

sd = math.sqrt(var)

print("Variance = %f"%var + "     sd = %f"%sd)

uvar = ssum / (len(data) - 1.0)

sd_uvar = math.sqrt(uvar)

print("Unbiased Var. = %f"%uvar + "     sd(uvar) = %f"%sd_uvar)

 

#

#       Check the minimum and maximum values

#

vmin = data[0]

n_max = n

vmax=data[0]

for x in data:

    if vmin > x: vmin = x

    if vmax < x: vmax = x

print("min = %f"%vmin + "   max = %f"%vmax)

n_bin = 10

while(True):

    mpt.title("Histogram")          #   The title of the histogram

    mpt.xlabel("Score")            #   The label of the x-axis

    mpt.ylabel("Frequency")       #   The label of the y-axis

    mpt.axis([vmin,vmax,0,n_max])   #   Set the boundaries of the axes

    mpt.hist(data, bins = n_bin)    #   Make the histogram

    mpt.show()                      #   Show the histogram

 

    n_bin = int(input("n_bin/%d = "%n_bin))     #   Set the number of

    if (n_bin < 2): break                       #   The program ended

    n_max = int(input("n_max/%d = "%n_max))     #   The upper boundary of the y-axis

    vmin = float(input("x_min/%f = "%vmin))     #   The left boundary of the x-axis

    vmax = float(input("x_max/%f = "%vmax))     #   The right boundary of the x-axis

==================================================

 

以下のwhile文内の繰り返し処理において枠の調整を行っている。

while(True):

    mpt.title("Histogram")          #   The title of the histogram

    mpt.xlabel("Score")            #   The label of the x-axis

    mpt.ylabel("Frequency")       #   The label of the y-axis

    mpt.axis([vmin,vmax,0,n_max])   #   Set the boundaries of the axes

    mpt.hist(data, bins = n_bin)    #   Make the histogram

    mpt.show()                      #   Show the histogram

 

    n_bin = int(input("n_bin/%d = "%n_bin))     #   Set the number of

    if (n_bin < 2): break                       #   The program ended

    n_max = int(input("n_max/%d = "%n_max))     #   The upper boundary of the y-axis

    vmin = float(input("x_min/%f = "%vmin))     #   The left boundary of the x-axis

    vmax = float(input("x_max/%f = "%vmax))     #   The right boundary of the x-axis

 

上のプログラムHistogram_2.pyを実行すると、図4のヒストグラムが表示される。

図4

 

画面の右上のX印をクリックして画面を閉じると、Python IDLEのコンソールが入力待ちの状態になる(図5)。

図5

 

適宜、適当な数値を入力していくが、ビンの数(ヒストグラムの区間数)として1以下の数を設定すると、プログラムの実行終了となる。

図6

 

直前の描画において用いられた値は、/の右側に表示されている。これらを参考にして、適当な値を入力していく(図6)。図6の状態でEnterキーを押すと、図7のヒストグラムが表示される。

図7

 

2変量の場合

散布図を描くプログラムScatter.pyを以下のように作成してみた。

================  Scatter.py  =========================

import math

import matplotlib.pyplot as plt

 

def sqr(x):

    return x * x

 

#

#       Data

#

pairs = [[70, 168], [68, 165], [62, 159], [56, 156], [70, 170],

         [64, 162], [59, 162], [70, 169], [68, 168], [69, 170],

         [67, 168], [63, 166], [58, 163], [74, 170], [65, 168],

         [60, 160], [65, 165], [72, 175], [61, 164], [77, 174],

         [68, 164], [64, 161], [70, 166], [47, 147], [66, 165],

         [68, 170], [73, 174], [74, 172], [63, 164], [83, 182],

         [58, 159], [64, 166], [67, 167], [75, 174], [67, 163],

         [68, 166], [68, 167], [66, 165], [63, 165], [55, 154],

         [61, 163], [60, 160], [62, 164], [62, 160], [59, 160],

         [51, 155], [59, 163], [68, 170], [56, 157], [79, 180]]

 

n = len(pairs)      #       The number of pairs (xi, yi)

print("n = %d"%n)

 

sum_x = 0.0

sum_y = 0.0

for i in range(0, n):

    sum_x += pairs[i][0]

    sum_y += pairs[i][1]

mean_x = sum_x / n

mean_y = sum_y / n

print("Mean_x = %f"%mean_x)

print("Mean_y = %f"%mean_y)

ssum_x = 0.0

ssum_y = 0.0

sum_xy = 0.0

for i in range(0, n):

    ssum_x += sqr(pairs[i][0] - mean_x)

    ssum_y += sqr(pairs[i][1] - mean_y)

    sum_xy += (pairs[i][0] - mean_x) * (pairs[i][1] - mean_y)

   

var_x = ssum_x / n                  #   Variance of X

var_y = ssum_y / n                  #   Variance of Y

print("Var_x = %f"%var_x)

print("Var_y = %f"%var_y)

sd_x = math.sqrt(var_x)             #   Standard deviation of X

sd_y = math.sqrt(var_y)             #   Standard deviation of Y

print("sd_x = %f"%sd_x)

print("sd_y = %f"%sd_y)

 

cor = sum_xy / math.sqrt(ssum_x * ssum_y)       #   The correlation coefficient

print("r = %f"%cor)

 

data_x = []     #   Values of the coordinate Xs of the pairs

data_y = []     #   Values of the coordinate Ys of the pairs

for i in range(0, n):

    data_x.append(pairs[i][0])

    data_y.append(pairs[i][1])

print(data_x)

print(data_y)

 

plt.title("Scattergram...r = %6.3f"%cor)            #   The title of the scattergram

plt.xlabel("Weight")                #   The label of the x-axis

plt.ylabel("Height")                #   The label of the y-axis

plt.plot(data_x, data_y, 'bo')      #   Make the scattergram.   'bo' -> blue circle

plt.show()                          #   Show the scattergram

=============================================

 

散布図描画の関数plotは、以下のように、X座標のリストdata_xとY座標のリストdata_yに分けて別個のパラメータとして渡している。

plt.plot(data_x, data_y, 'bo')      #   Make the scattergram.   'bo' -> blue circle

第3パラメータ「'bo’」は、散布図の点を青の円で描くことを指示するものである。

X座標のリストdata_xとY座標のリストdata_yを、[X座標、Y座標]のペアでデータが設定されているリストpairsから作成するために以下のコードを用いている。

data_x = []     #   Values of the coordinate Xs of the pairs

data_y = []     #   Values of the coordinate Ys of the pairs

for i in range(0, n):

    data_x.append(pairs[i][0])

    data_y.append(pairs[i][1])

 

プログラムScatter.pyを実行すると図8の散布図が表示される。なお、グラフの日本語表記については、本ウェブサイトの後半で説明している。

図8

 

 

 

ファイル入出力

入力データは、プログラム中に書き込むよりは別ファイルとして用意する方が便利である。また、出力もコンソールではなく、ファイルに出力した方が後で使いやすい。

 

1変量データの場合

表1のデータを、DataOneVar.txtとして以下のようなテキストファイルDataOneVar.txtとして用意した。このファイルは圧縮ファイルSmplStatPy.zipに含まれている。

 

============  DataOneVar.txt  ===================

 

/

    66

    59

    62

    64

    63

    68

    49

    69

    70

    80

    73

    72

/

 

=============================================

 

ファイル入出力に対応したプログラムStatOneVarF.pyは以下のように作成した。

 

===============  StatOneVarF.py  =====================

 

import math

import matplotlib.pyplot as mpt

 

def sqr(x):

    return x * x

 

#

#       Prepare the input data file

#

s_in = input("Input data file = ")

f_in = open(s_in, "r")

#

#       Set the contents of the input data file in the object data

#

data_f = f_in.readlines()

f_in.close()

#

#       Prepare the output file

#

s_out = input("Output data file = ")

f_out = open(s_out, "w")

f_out.write("Input data file = " + s_in + "\n\n")

 

pos = 0

while True:

    if data_f[pos].find("/", 0) == 0: break

    pos += 1

n = 0

data = []

while True:

    pos += 1

    if data_f[pos].find("/", 0) == 0: break

    data.append(float(data_f[pos]))

    n += 1

   

print("Data...")

i = 1

for x in data:

    f_out.write("%5d:"%i + "  %f\n"%x)

    i+=1

 

f_out.write("\n")

sum = 0.0

for x in data:

    sum += x

mean = sum / n

print("Mean = %f"%mean)

f_out.write("Mean = %f\n"%mean)

ssum = 0.0

for x in data:

    ssum += sqr(x - mean)

var = ssum / n

sd = math.sqrt(var)

print("Variance = %f"%var + "     sd = %f"%sd)

f_out.write("Variance = %f"%var + "     sd = %f\n"%sd)

uvar = ssum / (n - 1.0)

sd_uvar = math.sqrt(uvar)

print("Unbiased Var. = %f"%uvar + "     sd(uvar) = %f"%sd_uvar)

f_out.write("Unbiased Var. = %f"%uvar + "     sd(uvar) = %f\n"%sd_uvar)

 

 

f_out.close()

print(s_out + " was saved.")

 

 

vmin = data[0]

n_max = n

vmax=data[0]

for x in data:

    if vmin > x: vmin = x

    if vmax < x: vmax = x

print("min = %f"%vmin + "   max = %f"%vmax)

n_bin = 10

while(True):

    mpt.title("Histogram")

    mpt.xlabel("Scores")

    mpt.ylabel("Frequencies")

    mpt.axis([vmin,vmax,0,n_max])

    mpt.hist(data, bins = n_bin)

    mpt.show()

 

    n_bin = int(input("n_bin/%d = "%n_bin))

    if (n_bin < 2): break

    n_max = int(input("n_max/%d = "%n_max))

    vmin = float(input("x_min/%f = "%vmin))

    vmax = float(input("x_max/%f = "%vmax))

 

 

===========================================

 

次のコードによって、コンソールから入力した名前のファイルを入力ファイルとしている。

s_in = input("Input data file = ")

f_in = open(s_in, "r")

 

出力ファイルは以下のコードによって設定している。

s_out = input("Output data file = ")

f_out = open(s_out, "w")

 

入力データファイルの内容は、コード

data_f = f_in.readlines()

によってリストdata_fに設定されている。入力データファイルの構成(これはリストdata_fに文字列のリストとして取り込まれている)は、データの書かれている部分がスラッシュ / で始まる行で挟まれているので、以下のコードによってデータ(data_fの内容)をリストdataに設定している。

pos = 0

while True:

    if data_f[pos].find("/", 0) == 0: break

    pos += 1

n = 0

data = []

while True:

    pos += 1

    if data_f[pos].find("/", 0) == 0: break

    data.append(float(data_f[pos]))

    n += 1

 

この後の処理は、上のプログラムHistogram_2.pyに対応している。

プログラムを実行すると、まず、入力データファイル名を聞いてくる(図9)。

図9

 

入力データファイル名の設定後、Enterキーを押すと、次に出力ファイル名を聞いてくる(図10)。

図10

 

出力ファイル名として適当なテキストファイル名を設定してEnterキーを押すと計算が始まり、図11の画面が表示される。

図11

 

これは図4と同じである。操作も図4に対するものと同じように行えばよい。

プログラムの実行終了後、出力ファイルを開くと、入力データファイルDataOneStat.txtの場合は、出力ファイルは以下のようになっている。

 

================  ResultsOneVar.txt  ===================

Input data file = DataOneVar.txt

 

    1:  66.000000

    2:  59.000000

    3:  62.000000

    4:  64.000000

    5:  63.000000

   47:  70.000000

   48:  80.000000

   49:  73.000000

   50:  72.000000

 

Mean = 63.680000

Variance = 60.217600     sd = 7.760000

Unbiased Var. = 61.446531     sd(uvar) = 7.838784

=============================================

 

 

2変量データの場合

表2のデータから、以下のようにテキストファイルDataTwoVars.txtを作成した。このファイルも圧縮ファイルSmplStatPy.zipに含まれている。

 

=============  DataTwoVars.txt  =======================

 

/

    70  168

    68  165

    62  159

    56  156

    70  170

    64  162

    59  162

    62  160

    59  160

    51  155

    59  163

    68  170

    56  157

    79  180

/

 

==========================================

 

データがスラッシュ / で始まる行で挟まれているので、読み込み方は1変量のプログラムStatOneVarF.pyの場合と基本的に同じである。2変量用のプログラムScatterF.pyを以下のように作成した。

 

================  ScatterF.py  ========================

import math

import matplotlib.pyplot as mpt

 

def sqr(x):

    return x * x

 

#

#       Prepare the input data file

#

s_in = input("Input data file = ")

f_in = open(s_in, "r")

#

#       Set the contents of the input data file in the object data

#

data_f = f_in.readlines()

f_in.close()

#

#       Prepare the output file

#

s_out = input("Output data file = ")

f_out = open(s_out, "w")

f_out.write("Input data file = " + s_in + "\n\n")

 

pos = 0

while True:

    if data_f[pos].find("/", 0) == 0: break     #   Jump to teh first line with slash at the head

    pos += 1

           

n = 0

pairs = []

while True:

    pos += 1

    if data_f[pos].find("/", 0) == 0: break     #   Exit when the line with slash at the head is met

    #

    #       Add the data

    #

    temp_s = data_f[pos].split()

    pairs.append([])

    pairs[n].append(float(temp_s[0]))

    pairs[n].append(float(temp_s[1]))

    n += 1

 

f_out.write("\n")

f_out.write("The number of pairs = %d\n"%n)

f_out.write("Data...\n")

i = 1

for v in pairs:

    f_out.write("%5d:  %f  %f\n"%(i, v[0], v[1]))

    i += 1

 

sum_x = 0.0

sum_y = 0.0

for i in range(0, n):

    sum_x += pairs[i][0]

    sum_y += pairs[i][1]

mean_x = sum_x / n

mean_y = sum_y / n

print("Mean_x = %f"%mean_x)

print("Mean_y = %f"%mean_y)

f_out.write("\nMean_x = %f\n"%mean_x)

f_out.write("Mean_y = %f\n"%mean_y)

 

ssum_x = 0.0

ssum_y = 0.0

sum_xy = 0.0

for i in range(0, n):

    ssum_x += sqr(pairs[i][0] - mean_x)

    ssum_y += sqr(pairs[i][1] - mean_y)

    sum_xy += (pairs[i][0] - mean_x) * (pairs[i][1] - mean_y)

 

var_x = ssum_x / n                  #   Variance of X

var_y = ssum_y / n                  #   Variance of Y

print("Var_x = %f"%var_x)

print("Var_y = %f"%var_y)

f_out.write("Var_x = %f\n"%var_x)

f_out.write("Var_y = %f\n"%var_y)

sd_x = math.sqrt(var_x)             #   Standard deviation of X

sd_y = math.sqrt(var_y)             #   Standard deviation of Y

print("sd_x = %f"%sd_x)

print("sd_y = %f"%sd_y)

f_out.write("sd_x = %f\n"%sd_x)

f_out.write("sd_y = %f\n"%sd_y)

cor = sum_xy / math.sqrt(ssum_x * ssum_y)   #   The correlation coefficient

print("r = %f"%cor)

f_out.write("r = %f\n"%cor)

 

 

data_x = []     #   Values of the coordinate Xs of the pairs

data_y = []     #   Values of the coordinate Ys of the pairs

for i in range(0, n):

    data_x.append(pairs[i][0])

    data_y.append(pairs[i][1])

print(data_x)

print(data_y)

 

f_out.close()

print("Output file " + s_out + " was saved.")

 

mpt.title("Scattergram...r = %6.3f"%cor)

mpt.xlabel("Weight")

mpt.ylabel("Height")

mpt.plot(data_x, data_y, 'g^')      #   'g^' -> green triangle

mpt.show()

============================================

 

1行に1組のデータ、XとY、が含まれているので、それを分離してリストpairsに格納するため、以下のコードが用いられている。

    temp_s = data_f[pos].split()

    pairs.append([])

    pairs[n].append(float(temp_s[0]))

    pairs[n].append(float(temp_s[1]))

 

また、上のプログラムScatterF.pyでは、散布図の点が緑色の三角形で描かれるように、第3パラメータの値が「'g^’」となっている。

mpt.plot(data_x, data_y, 'g^')      #   'g^' -> green triangle

 

このとき、散布図は図12のように描かれる。

図12

 

出力ファイを図13の名前ResultsTwoVars.txtで設定すると、

図13

 

その内容は以下に示すようになっている。

 

===============  ResultsTwoVars.txt  ======================

 

Input data file = DataTwoVars.txt

 

 

The number of pairs = 50

Data...

    1:  70.000000  168.000000

    2:  68.000000  165.000000

    3:  62.000000  159.000000

    4:  56.000000  156.000000

    5:  70.000000  170.000000

   45:  59.000000  160.000000

   46:  51.000000  155.000000

   47:  59.000000  163.000000

   48:  68.000000  170.000000

   49:  56.000000  157.000000

   50:  79.000000  180.000000

 

Mean_x = 65.240000

Mean_y = 165.300000

Var_x = 46.822400

Var_y = 40.130000

sd_x = 6.842690

sd_y = 6.334824

r = 0.942805

===============================================

 

上の計算結果は、図2に示されている計算結果と同じであることが確認できる。

 

 

グラフの日本語表示(モジュールjapanize_matplotlibによる場合)

グラフ描画のモジュールmatplotlibに加えて、モジュールjapanize_matplotlibimportすると日本語が表示できる。

モジュールjapanize_matplotlibはコマンドpipでインストールできる。

 

pip install japanize_matplotlib

 

と実行すればよい。しかし、Anacondacondaコマンドではインストールできなかった(2020.0613)が、pipコマンドでインストールすることができた。

ヒストグラムの日本語表記のサンプルプログラムは以下のようである。

 

import matplotlib.pyplot as mpt

import japanize_matplotlib

import math

 

def sqr(x):

    return x * x

 

data = [66, 59, 62, 64, 63,

        68, 65, 59, 68, 64,

        65, 51, 67, 64, 83,

        59, 61, 62, 57, 72,

        65, 64, 54, 60, 53,

        65, 67, 60, 53, 79,

        74, 53, 61, 68, 75,

        50, 57, 55, 66, 56,

        55, 61, 70, 71, 49,

        69, 70, 80, 73, 72]

 

n = len(data)           #  The number of scores

print("個数 = {}".format(n))

 

print("データ...")

i = 1

for x in data:

    print("{0:}:  {1:}".format(i, x))

    i+=1

 

mpt.title("ヒストグラム")       #   タイトル

mpt.xlabel("スコア")            #   X軸のラベル

mpt.ylabel("度数")              #   Y軸のラベル

mpt.hist(data, bins = 10)       #   ヒストグラムの描画

mpt.show()                      #   描画グラフの表示

 

上のスクリプトを実行すると、下図のグラフが表示される。

 

 

散布図の場合のプログラム例を以下に示す。

 

import math

import matplotlib.pyplot as plt

import japanize_matplotlib

 

def sqr(x):

    return x * x

 

#

#       Data

#

pairs = [[70, 168], [68, 165], [62, 159], [56, 156], [70, 170],

         [64, 162], [59, 162], [70, 169], [68, 168], [69, 170],

         [67, 168], [63, 166], [58, 163], [74, 170], [65, 168],

         [60, 160], [65, 165], [72, 175], [61, 164], [77, 174],

         [68, 164], [64, 161], [70, 166], [47, 147], [66, 165],

         [68, 170], [73, 174], [74, 172], [63, 164], [83, 182],

         [58, 159], [64, 166], [67, 167], [75, 174], [67, 163],

         [68, 166], [68, 167], [66, 165], [63, 165], [55, 154],

         [61, 163], [60, 160], [62, 164], [62, 160], [59, 160],

         [51, 155], [59, 163], [68, 170], [56, 157], [79, 180]]

 

n = len(pairs)      #       データ(Xi, Yi)の個数

print("個数 = {}".format(n))

 

sum_x = 0.0

sum_y = 0.0

for i in range(0, n):

    sum_x += pairs[i][0]

    sum_y += pairs[i][1]

mean_x = sum_x / n

mean_y = sum_y / n

print("Xの平均 = {0:.2f}".format(mean_x))

print("Yの平均 = {0:.2f}".format(mean_y))

ssum_x = 0.0

ssum_y = 0.0

sum_xy = 0.0

for i in range(0, n):

    ssum_x += sqr(pairs[i][0] - mean_x)

    ssum_y += sqr(pairs[i][1] - mean_y)

    sum_xy += (pairs[i][0] - mean_x) * (pairs[i][1] - mean_y)

   

var_x = ssum_x / n                  #   Xの分散

var_y = ssum_y / n                  #   Yの分散

print("Xの分散 = {0:.2f}".format(var_x))

print("Yの分散 = {0:.2f}".format(var_y))

sd_x = math.sqrt(var_x)             #   Xの標準偏差

sd_y = math.sqrt(var_y)             #   Yの標準偏差

print("Xの標準偏差 = {0:.2f}".format(sd_x))

print("Yの標準偏差 = {0:.2f}".format(sd_y))

 

cor = sum_xy / math.sqrt(ssum_x * ssum_y)       #   相関係数

print("相関係数 = {0:.3}".format(cor))

 

data_x = []     #   データ(X, Y)Xを設定

data_y = []     #   データ(X< Y)Yを設定

for i in range(0, n):

    data_x.append(pairs[i][0])

    data_y.append(pairs[i][1])

print(data_x)

print(data_y)

 

plt.title("散布図...r = {0:.3}".format(cor), fontsize = 16)      #   グラフのタイトル

plt.xlabel("体重", fontsize = 14)     #   X軸のラベル

plt.ylabel("身長", fontsize = 14)     #   Y軸のラベル

plt.plot(data_x, data_y, 'bo')        #   散布図の作成.   'bo' -> 青の小円

plt.show()                            #   グラフの表示

 

上のプログラムを実行すると下図のグラフが表示される。

 

 

グラフの日本語表示(モジュールjapanize_matplotlibによらない場合)

モジュールjapanize_matplotlibを用いず、matplotlib.pyplotの関数rcParamsによってフォントの設定を行う例を以下に示す。

 

import scipy.stats as ss

import matplotlib.pyplot as plt

 

d_r0 = ss.multivariate_normal.rvs([0, 0], [[1, 0], [0, 1]], size = 100)

d_r09 = ss.multivariate_normal.rvs([0,0], [[1, 0.9], [0.9, 1]], size = 100)

 

plt.rcParams['font.family'] = 'Yu Gothic'

 

plt.figure(figsize = (7, 7))

plt.title('散布図', fontsize = 30)

plt.plot(d_r0[:,0], d_r0[:, 1], 'go', label = '相関係数 = 0')

plt.plot(d_r09[:, 0], d_r09[:, 1], 'bo', label = '相関係数 = 0.9')

plt.xlabel('X', fontsize = 20)

plt.ylabel('Y', fontsize = 20)

plt.xlim(-3.5, 3.5)

plt.ylim(-3.5, 3.5)

plt.legend(loc = 'lower right', fontsize = 16)

plt.show()

 

上の例では、Windowsでの場合なので

 

plt.rcParams['font.family'] = 'Yu Gothic'

 

としているが、他のOS、例えばubuntuであれば、他のフォントを指定して

 

plt.rcParams['font.family'] = 'Noto Sans CJK JP'

 

などとすればよい。

複数のOSで共通に使うときは、可能性のあるフォントを並べて、

 

plt.rcParams['font.family'] = ['Yu Gothic', Noto Sans CJK JP, Hiragino Maru Gothic Pro]

 

などとすればよい。ただし、この方法は、インストールされていないフォントに対しては、その旨のメッセージが出力されるようになった(2023.02.23)。

インストールされているフォントを調べる方法については、このウェブサイトを参照されたい。

 

上のリストを実行すると下図のグラフが表示される。

 

 

Home