統計分析とPythonプログラミング
平均・分散・標準偏差・相関係数・棒グラフ・折れ線グラフ・ヒストグラム・散布図
本ウェブサイトは、このウェブサイトの説明を詳しくしたものである。サンプルスクリプトなどのファイルは、圧縮ファイルSimpleStatDetailed.zipにまとめた。ダウンロード展開すれば、自由に利用できる。
なお、統計学についての解説を<岡本安晴「データを使いこなすための統計入門」22世紀アート>で行っている。
また、Pythonデータ分析の解説を<岡本安晴「いまさら聞けないPythonでデータ分析」丸善出版>で行っている。
表M.1の10個のデータの和を求めてみる。
表M.1 10個のデータ |
66, 59, 62, 64, 63,68, 65, 59, 68, 64 |
まず、10個のデータの和は、10個のデータをリストdataで表して、リストの要素を1つずつ足して求めることができる。すなわち、次のスクリプト
data = [66, 59, 62, 64, 63,68, 65, 59,
68, 64]
s = 0
for v in data:
s += v
print('s =', s)
を実行すると、次のように和が表示される。
s = 638
平均は、データの和をデータ全体に等しく分けたときの1個当たりの値であるので、和を個数で割った値、すなわち次のスクリプトで求めることができる。
m = s / len(data)
print('m =', m)
上のスクリプトを実行すると、次の出力を得る。
m = 63.8
和は、和を求める関数sumを用いると、次のスクリプトで求めることができる。
s1 = sum(data)
print('s1 =', s1)
上のスクリプトを実行すると、次の出力を得る。
s1 = 638
平均値は、ライブラリnumpyの関数meanで求めることができる。
ライブラリnumpyは次のコマンドでインストールできる。
PS
C:\Users\Yasuharu> pip install numpy
次のスクリプトはnumpyの関数meanにより平均を求めるものである。
import numpy
m1 = numpy.mean(data)
print('m1 =', m1)
実行すると、次の出力を得る。
m1 = 63.8
以上のスクリプトをリストM.1のようにまとめた。
リストM.1 平均値の計算例(calc_mean_1.py)
data = [66, 59, 62, 64, 63,68, 65, 59,
68, 64]
s = 0
for v in data:
s += v
print('s =', s)
m = s / len(data)
print('m =', m)
s1 = sum(data)
print('s1 =', s1)
import numpy
m1 = numpy.mean(data)
print('m1 =', m1)
リストM.1を実行すると、以下の出力を得る。
s = 638
m = 63.8
s1 = 638
m1 = 63.8
データが、表計算ソフトで表の形で用意されている場合を考える。表計算ソフトは、Excelとか(無料)Open Office Calcがある。図M.1は、Open Office Calcで表を用意したものである。
図M.1
ファイル拡張子を「.csv」に指定すると、CSV形式のファイルとして保存される。CSV形式は、岡本(2019)、pp. 33-35でも説明している。
CSV形式のファイルとして用意されたデータの読み込みは、モジュールpandasを用いると簡単にできる。
CSVファイルは、プログラムから読み込む前に保存しておく必要がある。既にあるファイルを修正した場合も、保存の操作を行わないと、修正したデータの読み込みはできない。また、データの保存は、スクリプトファイルと同じフォルダに保存しておくと、プログラムからファイル名を指定するときに簡単である。
図M.1のファイルonecol.csvは、次のコードで読み込める。
csv_data =
pandas.read_csv('onecol.csv')
上のコードにより、CSV形式のデータファイルonecol.csvが読み込まれて、pandasのDataFrameという型のオブジェクトに変換される。DataFrameは辞書型のリストのようなもので、いろいろ便利な機能が用意されている。
DataFrame型のオブジェクトcsv_dataを、次のコードで書き出してみる。
print('csv_data
=\n', csv_data)
以下の出力を得る。
csv_data =
66
0
59
1
62
2
64
3
63
4
68
5
65
6
59
7
68
8
64
最初の「66」はキーとして扱われている。左1列目の数字は、データの通し番号である。読み込まれた値は、キーの下に書き出されている。
データの値だけを取り出すときは、アトリビュートvaluesで取り出せる。
csv_data.values
次のコードは、取り出した値を出力するものである。
print('\ncsv_data.values
=\n', csv_data.values)
上のコードにより、以下の出力が得られる。
csv_data.values =
[[59]
[62]
[64]
[63]
[68]
[65]
[59]
[68]
[64]]
9行×1行の配列の形になっている。これは、numpyの配列型ndarray型である。アトリビュートvaluesにより、値がndarray型として得ることができる。Numpyの配列ndarrayは、いろいろ便利な機能が用意されている配列である。
上の例では、図M.1の表において、1行目がDataFrameのキーとして扱われていて、データの値から抜けている。1行目からデータとして取り込むときは、パラメータheader=Noneを指定して読み込む。次のコードで読み込むと、1行目からデータの値として取り込める。
csv_data =
pandas.read_csv('onecol.csv', header=None)
1行目がデータの値として取り込めていることは、上のコードに続けて以下のコードを実行すると確かめることができる。
print(csv_data)
print('\n', csv_data.values)
上のコードを実行すると、以下の出力を得る。
0
0
66
1
59
2
62
3
64
4
63
5
68
6
65
7
59
8
68
9
64
[[66]
[59]
[62]
[64]
[63]
[68]
[65]
[59]
[68]
[64]]
DataFrameのキーとして、0が自動生成されていることが分かる。
平均値は、numpyの関数numpy.meanで計算できる。
m =
numpy.mean(csv_data.values)
print('\nMean
=', m)
上のスクリプトを実行すると、次の出力を得る。
Mean = 63.8
上の説明を、リストM.2にまとめた。
リストM.2 CSVファイルからの読み込み(calc_onecol.py)
import numpy
import pandas
csv_data =
pandas.read_csv('onecol.csv')
print('csv_data =\n', csv_data)
print('\ncsv_data.values =\n', csv_data.values)
print('\nheader=None')
csv_data =
pandas.read_csv('onecol.csv', header=None)
print(csv_data)
print('\n', csv_data.values)
m = numpy.mean(csv_data.values)
print('\nMean =', m)
リストM.2を実行すると、以下の出力を得る。
csv_data =
66
0
59
1
62
2
64
3
63
4
68
5
65
6
59
7
68
8
64
csv_data.values =
[[59]
[62]
[64]
[63]
[68]
[65]
[59]
[68]
[64]]
header=None
0
0
66
1
59
2
62
3
64
4
63
5
68
6
65
7
59
8
68
9
64
[[66]
[59]
[62]
[64]
[63]
[68]
[65]
[59]
[68]
[64]]
Mean = 63.8
変数が複数の場合は、以下のようになる。
図M.2のCSVファイルは、2変数XとYの場合である。
図M.2
図M.2のファイルを、次のコードで読み込んでみる。
csv_data =
pandas.read_csv('twocols.csv')
読み込まれたデータは、DataFrame型のオブジェクトとして作成されている。次のコードで書き出してみる。
print('csv_data
=\n', csv_data)
以下の出力を得る。
csv_data =
X Y
0
1 4
1
2 5
2
3 6
DataFrameのキーとしてXとYが設定されている。これは、CSVファイルから読み込むときに、1行目に設定されているものである。
1列目は、データの通し番号である。
データの値だけを取り出すときは、アトリビュートvaluesを用いる。
data =
csv_data.values
取り出した値を、次のコードで出力してみる。
print('\ndata
=\n', data)
実行すると、以下の出力を得る。
data =
[[1 4]
[2 5]
[3 6]]
3行×2列のndarray型の配列として得られていることが分かる。
DataFrameのキーは、次のコードで得ることができる。
var_names =
[v for v in csv_data.keys()]
次のコードで、出力してみる。
print('\nvar_names
=', var_names)
実行すると、次の出力を得る。
var_names =
['X', 'Y']
データ全体の平均は、numpyの関数meanで求めることができる。
print('mean
=', numpy.mean(data))
上のコードを実行すると、次の出力を得る。
mean = 3.5
列単位での平均を求めるときは、パラメータaxis=0、行単位で平均をとるときはパラメータaxis=1を付ける。
print('mean(axis=0) =',
numpy.mean(data, axis=0))
print('mean(axis=1) =',
numpy.mean(data, axis=1))
上のスクリプトを実行すると、次の出力を得る。
mean(axis=0) = [2. 5.]
mean(axis=1) = [2.5 3.5 4.5]
上の説明をリストM.3にまとめた。
リストM.3 複数の変数からなるCSVファイルの読み込み(calc_twocols.py)
import numpy
import pandas
csv_data =
pandas.read_csv('twocols.csv')
print('csv_data =\n', csv_data)
data = csv_data.values
print('\ndata =\n', data)
var_names = [v for v in
csv_data.keys()]
print('\nvar_names =', var_names)
print('mean =', numpy.mean(data))
print('mean(axis=0) =',
numpy.mean(data, axis=0))
print('mean(axis=1) =',
numpy.mean(data, axis=1))
リストM.3を実行すると、以下の出力を得る。
csv_data =
X Y
0
1 4
1
2 5
2
3 6
data =
[[1 4]
[2 5]
[3 6]]
var_names = ['X', 'Y']
mean = 3.5
mean(axis=0) = [2. 5.]
mean(axis=1) = [2.5 3.5 4.5]
データの値、・・・、の散らばりの程度を表す指標として、分散あるいは標準偏差などがある。
いま、平均値を
と置いたとき、散らばり具合を、データの各値が平均値からどれくらい離れているかを表すと、次の値
は、データ値が平均値より大きいとき正の値、データ値が平均値より小さいとき負の値を取る。2乗して正の値にしてから平均を求める。
このは、分散(variance)と呼ばれている。
分散は、サンプルデータの散らばりを表すものである。データがある母集団からのサンプルであると考えた場合には、データから算出された分散は母集団の分散より小さくなる傾向(バイアス)があるので、母集団の分散の推定値としてのバイアスを補正した値
が使われる。は不偏分散と呼ばれている。分散の存在しない(無限大)分布もあるので、不偏分散が常に意味を持つとは限らない。
分散は、2乗和であるので、例えば、体重のデータの場合、単位がとなる。これをに戻すために平方根を取ると説明されることがある。
分散あるいは不偏分散の平方根は標準偏差(standard deviation)と呼ばれている。
具体的に、表V.1のデータについて考える。
表V.1 |
3, 6, 4, 5 |
表V.1のデータの平均は
である。したがって、分散は
となる。不偏分散は
である。
分散から導かれる標準偏差は
不偏分散から導かれる標準偏差は
である。
上の計算をPythonスクリプトで行ってみる。
表V.1のデータをリストで表してみる。
data = [3,6,4,5]
print('data =', data)
上のスクリプトを実行すると、次の出力を得る。
data = [3, 6,
4, 5]
配列の計算は、numpyのndarray型を用いると便利であるので、次のようにリストdataをnumpyのndarray型に変換する。
import numpy
as np
a =
np.array(data)
print('a =',
a)
上のスクリプトを実行すると、次の出力を得る。
a = [3 6 4 5]
平均は、numpyの関数meanにより求めることができる。
m = np.mean(a)
print('mean =', m)
上のスクリプトを実行すると、次の出力を得る。
mean = 4.5
データと平均との差は、次のスクリプトで求まる。
a_m = a - m
print('a - m =', a_m)
実行すると、次の出力を得る。
a - m =
[-1.5 1.5 -0.5 0.5]
データと平均との差の2乗は、次のスクリプトで得ることができる。
ss = a_m ** 2
print('ss =',
ss)
実行すると、次の出力を得る。
ss = [2.25 2.25 0.25 0.25]
従って、分散は差の2乗の平均として、次のスクリプトで求めることができる。
var = np.mean(ss)
print('var =', var)
実行すると、次の出力を得る。
var = 1.25
不偏分散(unbiased variance)は、次のスクリプトで得ることができる。
var_u = np.sum(ss) / (len(a) - 1)
print('var_u =', var_u)
実行すると、次の出力を得る。
var_u =
1.6666666666666667
標準偏差(standard deviation)は、分散の平方根として次のスクリプトで得ることができる。
sd_var = var ** 0.5
print('sd(var) =', sd_var)
sd_var_u = var_u ** 0.5
print('sd(var_u) =', sd_var_u)
実行すると、以下の出力を得る。
sd(var) = 1.118033988749895
sd(var_u) = 1.2909944487358056
分散と標準偏差は、numpyの関数によって求めることもできる。パラメータddof=1を設定すると不偏分散が算出される。
var_1 = np.var(a)
print('var_1 =', var_1)
var_u_1 = np.var(a, ddof=1)
print('var_u_1 =', var_u_1)
sd_var_1 = np.std(a)
print('sd_var_1 =', sd_var_1)
sd_var_u_1 = np.std(a, ddof=1)
print('sd_var_u_1 =', sd_var_u_1)
上のスクリプトを実行すると、以下の出力が得られる。
var_1 = 1.25
var_u_1 = 1.6666666666666667
sd_var_1 = 1.118033988749895
sd_var_u_1 = 1.2909944487358056
上の説明をまとめると、リストV.1のようになる。
リストV.1 分散・標準偏差の計算(calc_var_sd.py)
data = [3,6,4,5]
print('data =', data)
import numpy as np
a = np.array(data)
print('a =', a)
m = np.mean(a)
print('mean =', m)
a_m = a - m
print('a - m =', a_m)
ss = a_m ** 2
print('ss =', ss)
var = np.mean(ss)
print('var =', var)
var_u = np.sum(ss) / (len(a) - 1)
print('var_u =', var_u)
sd_var = var ** 0.5
print('sd(var) =', sd_var)
sd_var_u = var_u ** 0.5
print('sd(var_u) =', sd_var_u)
print()
var_1 = np.var(a)
print('var_1 =', var_1)
var_u_1 = np.var(a, ddof=1)
print('var_u_1 =', var_u_1)
sd_var_1 = np.std(a)
print('sd_var_1 =', sd_var_1)
sd_var_u_1 = np.std(a, ddof=1)
print('sd_var_u_1 =', sd_var_u_1)
リストV.1を実行すると、以下の出力を得る。
data = [3, 6, 4, 5]
a = [3 6 4 5]
mean = 4.5
a - m = [-1.5 1.5 -0.5 0.5]
ss = [2.25 2.25 0.25 0.25]
var = 1.25
var_u = 1.6666666666666667
sd(var) = 1.118033988749895
sd(var_u) = 1.2909944487358056
var_1 = 1.25
var_u_1 = 1.6666666666666667
sd_var_1 = 1.118033988749895
sd_var_u_1 = 1.2909944487358056
標準得点(standardized score):z得点(z score)
CSVファイルへの保存
例えば、身長のデータは、mを単位とする場合とpを単位とする場合とで数値が100倍異なる。データの単位の影響を除いて、データの統計学的分析を行うときには、データを平均が0,分散が1であるように変換した値が用いられる。この値はz得点と呼ばれているが、一般に、データを何らかの基準で標準化した値は、標準得点(standardized score)と呼ばれている(岡本、2022、pp. 18-19)。
z得点は、次式で求められる。
図V.1のデータについて考える。
図V.1
次のスクリプトで、図V.1のCSV形式のファイルdata.csvをpandasのDataFrame型のオブジェクトとして読み込み、csv_dataで指し示す。
csv_data =
pd.read_csv('data.csv')
読み込まれたDataFrame型のオブジェクトのキーとデータ値は、次のスクリプトで表示できる。
print('csv_data
=\n', csv_data)
names = [v
for v in csv_data.keys()]
print('names
=\n', names)
data =
csv_data.values
print('data
=\n', data)
上のスクリプトを実行すると、以下の出力を得る。
csv_data =
X Y
0
3 30
1
6 60
2
4 40
3
5 50
names =
['X', 'Y']
data =
[[ 3 30]
[ 6 60]
[ 4 40]
[ 5 50]]
次のコードで、csv_dataのキー「'X'」のデータを取りだし、Xで指し示す。
X = np.array(csv_data['X'])
print('X =\n', X)
上のコードを実行すると、次の出力を得る。
X =
[3 6 4 5]
平均と標準偏差は次のスクリプトで求められる。
meanX = np.mean(X)
sdX = np.std(X)
print('meanX =', meanX, ' sdX =', sdX)
上のスクリプトを実行すると、次の出力を得る。
meanX =
4.5 sdX =
1.118033988749895
これらより、のz得点、は次のスクリプトで求められ、配列z_Xで表される。
z_X = (X - meanX) / sdX
print('z_X =\n', z_X)
上のスクリプトを実行すると、次の出力を得る。
z_X =
[-1.34164079 1.34164079 -0.4472136 0.4472136 ]
DataFrame csv_dataのキー「'Y'」のデータも、Yで表して、上の処理と同様に以下のスクリプトによる処理を行う。
Y = np.array(csv_data['Y'])
print('Y =\n', Y)
meanY = np.mean(Y)
sdY = np.std(Y)
print('meanY =', meanY, ' sdY =', sdY)
z_Y = (Y - meanY) / sdY
print('z_Y =\n', z_Y)
実行すると、以下の出力を得る。
Y =
[30 60 40 50]
meanY = 45.0 sdY = 11.180339887498949
z_Y =
[-1.34164079 1.34164079 -0.4472136 0.4472136 ]
Yは、Xを10倍したものなので、2つのz得点z_Xとz_Yは同じ値である。
上で得られたz得点を、DataFrame csv_dataにキー「'z_X'」および「'z_Y'」のもとに追加する。
csv_data['z_X'] = z_X
csv_data['z_Y'] = z_Y
print(csv_data)
上のスクリプトを実行すると、以下の出力を得る。
X Y z_X z_Y
0
3 30 -1.341641 -1.341641
1
6 60 1.341641 1.341641
2
4 40 -0.447214 -0.447214
3
5 50 0.447214 0.447214
キー「'z_X'」および「'z_Y'」のデータの追加されたDataFrame csv_dataを、DataFrameのcsv_data.to_csv関数によりCSV形式のファイルcheck_1.csvに格納する。ファイル名は、拡張子「.csv」を付けて任意である。
with open('check_1.csv', 'w') as
f_csv:
csv_data.to_csv(f_csv,
index=False, lineterminator='\n')
上のスクリプトの実行後、CSVファイルcheck_1.csvを開くと、図V.2のようである。
図V.2
z得点は、ライブライscipyの関数scipy.stats.zscoreで求めることもできる。
import scipy
z = scipy.stats.zscore(X)
print('z =\n', z)
上のスクリプトを実行すると、以下の出力を得る。
z =
[-1.34164079 1.34164079 -0.4472136 0.4472136 ]
上の説明を、リストV.2にまとめた。
リストV.2 z得点(calc_z_score.py)
import numpy as np
import pandas as pd
csv_data = pd.read_csv('data.csv')
print('csv_data =\n', csv_data)
names = [v for v in csv_data.keys()]
print('names =\n', names)
data = csv_data.values
print('data =\n', data)
X = np.array(csv_data['X'])
print('X =\n', X)
meanX = np.mean(X)
sdX = np.std(X)
print('meanX =', meanX, ' sdX =', sdX)
z_X = (X - meanX) / sdX
print('z_X =\n', z_X)
Y = np.array(csv_data['Y'])
print('Y =\n', Y)
meanY = np.mean(Y)
sdY = np.std(Y)
print('meanY =', meanY, ' sdY =', sdY)
z_Y = (Y - meanY) / sdY
print('z_Y =\n', z_Y)
csv_data['z_X'] = z_X
csv_data['z_Y'] = z_Y
print(csv_data)
with open('check_1.csv', 'w') as
f_csv:
csv_data.to_csv(f_csv, index=False,
lineterminator='\n')
import scipy
z = scipy.stats.zscore(X)
print('z =\n', z)
リストV.2を実行すると、以下の出力を得る。
csv_data =
X Y
0
3 30
1
6 60
2
4 40
3
5 50
names =
['X', 'Y']
data =
[[ 3 30]
[ 6 60]
[ 4 40]
[ 5 50]]
X =
[3 6 4 5]
meanX = 4.5 sdX = 1.118033988749895
z_X =
[-1.34164079 1.34164079 -0.4472136 0.4472136 ]
Y =
[30 60 40 50]
meanY = 45.0 sdY = 11.180339887498949
z_Y =
[-1.34164079 1.34164079 -0.4472136 0.4472136 ]
X Y z_X z_Y
0
3 30 -1.341641 -1.341641
1
6 60 1.341641 1.341641
2
4 40 -0.447214 -0.447214
3
5 50 0.447214 0.447214
z =
[-1.34164079 1.34164079 -0.4472136 0.4472136 ]
2つの変量の増減の関係を考える。
図C.1のデータの場合、Xの値が増加するとYの値も増加している。
図C.1 SamplePのデータ
図C.2のデータの場合、Xの値が増加すると、Yの値は減少している。
図C.2 SampleNのデータ
2つのデータをまとめて散布図で表すと、図C.3のようになる。
図C.3
平均値(赤の星印の位置)からXの値が増加するとYの値はSamplePでは平均値から増加しており、SampleNでは減少している。平均値からXの値が減少すると、Yの値はSamplePでは減少しており、SampleNでは増加している。この関係は次の式(C.1)の値に反映される。
すなわち、SamplePでは式(C.1)の値は常に正であり、SampleNでは負である。
実際のデータでは、式(C.1)の値がすべてのデータの対に対して正、あるいは負であるとは限らないので、平均値をとってデータ全体の傾向を見る。このデータ全体にわたる式(C.1)の平均値は、共分散(covariance)と呼ばれている。
いま、データSampleP(図C.1)を次のスクリプトで読み込む。
import pandas as pd
import numpy as np
with open('SampleP.csv', 'r') as f:
csv_data = pd.read_csv(f)
print('csv_data =\n', csv_data)
X = np.array(csv_data['X'])
print('X =\n', X)
Y = np.array(csv_data['Y'])
print('Y =\n', Y)
上のスクリプトを実行すると、以下の出力を得る。
csv_data =
X Y
0
1 1
1
2 2
2
3 4
3
4 5
X =
[1 2 3 4]
Y =
[1 2 4 5]
1列目のデータがXに、2列目のデータがYに設定されたことが分かる。
XとY、それぞれの平均値を求め、式(C.2)により共分散を求めるスクリプトを以下のように用意した。
mean_X = np.mean(X)
mean_Y = np.mean(Y)
cov = np.mean((X - mean_X) * (Y -
mean_Y))
print('cov =', cov)
実行すると、次の結果を得る。
cov = 1.75
Pythonには、共分散を求める関数が用意されている。次のスクリプトは、Numpyの関数covを用いた例である。
ck_cov = np.cov(X, Y, ddof=0)
print('ck_cov =', ck_cov)
引数ddof=0は、平均を求めるときにデータ数で割ることを指定するものである。
実行すると、次の出力を得る。
ck_cov = [[1.25 1.75]
[1.75 2.5 ]]
関数covは、共分散行列を返すので、対角線上に分散、非対角要素に共分散が格納されている。
対角線上に分散が格納されていることを確認するために、次のスクリプトを用意した。
print('V(X)
=', np.var(X), ' V(Y) =',
np.var(Y))
実行すると、次の結果を得る。
V(X) =
1.25 V(Y) = 2.5
共分散は、2変数の間の関係を表すが、その大きさは変量の単位にも依存している。身長と体重の関係を共分散で表すとき、pとgの場合の値は、mとsの場合の100,000倍になる。単位の影響を避けるため、単位を統計学的な単位とした標準得点の共分散が用いられ、この場合の共分散は相関係数と呼ばれている。すなわち、
である。
コーシー・シュワルツの不等式(岡本、2009、p.54)から
が直ちに導かれるので、
の成り立つことが分かる。
XとYの標準得点を求め、その共分散として相関係数を求めるスクリプトを以下のように用意した。標準得点の平均は0であることに注意。
z_X = (X - mean_X) / np.std(X)
z_Y = (Y - mean_Y) / np.std(Y)
print('z_X =\n', z_X)
print('z_Y =\n', z_Y)
corr = np.mean(z_X * z_Y)
print('corr =', corr)
上のスクリプトを実行すると、以下の出力を得る。
z_X =
[-1.34164079 -0.4472136 0.4472136 1.34164079]
z_Y =
[-1.26491106 -0.63245553 0.63245553 1.26491106]
corr = 0.9899494936611666
numpyの相関係数を求める関数corrcoefを用いるスクリプトは、次のようになる。
corr_ck = np.corrcoef(X, Y)
print('corr_ck =', corr_ck)
関数corrcoefの返り値は相関行列であるので、上のスクリプトの実行結果は次のようになる。
corr_ck = [[1.
0.98994949]
[0.98994949 1. ]]
Scipyの関数pearsonrを用いる場合のスクリプトは以下のようである。式(C.3)で与えられる相関係数は、ピアソンの積率相関係数と呼ばれている。
import scipy
corr_ck1 = scipy.stats.pearsonr(X,
Y).statistic
print('corr_ck1 =\n', corr_ck1)
相関係数は、関数pearsonrの戻り値のstatisticの値として与えられる。
上のスクリプトを実行すると、次の出力を得る。
corr_ck1 =
0.9899494936611666
上の説明を、リストC.1としてまとめた。
リストC.1 相関係数の計算(calc_corr.py)
import pandas as pd
import numpy as np
with open('SampleP.csv', 'r') as f:
csv_data = pd.read_csv(f)
print('csv_data =\n', csv_data)
X = np.array(csv_data['X'])
print('X =\n', X)
Y = np.array(csv_data['Y'])
print('Y =\n', Y)
mean_X = np.mean(X)
mean_Y = np.mean(Y)
cov = np.mean((X - mean_X) * (Y -
mean_Y))
print('cov =', cov)
ck_cov = np.cov(X, Y, ddof=0)
print('ck_cov =', ck_cov)
print('V(X) =', np.var(X), ' V(Y) =', np.var(Y))
z_X = (X - mean_X) / np.std(X)
z_Y = (Y - mean_Y) / np.std(Y)
print('z_X =\n', z_X)
print('z_Y =\n', z_Y)
corr = np.mean(z_X * z_Y)
print('corr =', corr)
corr_ck = np.corrcoef(X, Y)
print('corr_ck =', corr_ck)
import scipy
corr_ck1 = scipy.stats.pearsonr(X,
Y).statistic
print('corr_ck1 =\n', corr_ck1)
リストC.1を実行すると、以下の出力を得る。
csv_data =
X Y
0
1 1
1
2 2
2
3 4
3
4 5
X =
[1 2 3 4]
Y =
[1 2 4 5]
cov = 1.75
ck_cov = [[1.25 1.75]
[1.75 2.5 ]]
V(X) = 1.25 V(Y) = 2.5
z_X =
[-1.34164079 -0.4472136 0.4472136 1.34164079]
z_Y =
[-1.26491106 -0.63245553 0.63245553 1.26491106]
corr = 0.9899494936611666
corr_ck = [[1.
0.98994949]
[0.98994949 1. ]]
corr_ck1 =
0.9899494936611666
リストC.1のスクリプトにおいて、入力ファイルを図C.2のSampleN.csvとするために、
with open('SampleN.csv', 'r') as f:
csv_data = pd.read_csv(f)
と変えて実行すると、以下のように負の相関係数が得られる。
csv_data =
X Y
0
1 5
1
2 4
2
3 2
3
4 1
X =
[1 2 3 4]
Y =
[5 4 2 1]
cov = -1.75
ck_cov = [[ 1.25 -1.75]
[-1.75 2.5 ]]
V(X) = 1.25 V(Y) = 2.5
z_X =
[-1.34164079 -0.4472136 0.4472136 1.34164079]
z_Y =
[ 1.26491106 0.63245553 -0.63245553 -1.26491106]
corr = -0.9899494936611666
corr_ck = [[ 1.
-0.98994949]
[-0.98994949 1. ]]
corr_ck1 =
-0.9899494936611666
Pythonにおける統計関係の関数について
Pythonにも統計関係の関数が多数用意されている。以下のウェブサイト
https://numpy.org/doc/stable/reference/routines.statistics.html
https://docs.scipy.org/doc/scipy/reference/stats.html
などを参照されたい。
図B.1のデータは、e-Statからダウンロードした(2023.11.22)統計名「国民栄養・健康調査」、表番号14のデータから2019年の20歳〜29歳の身長データを抜き出したものである。
図B.1
身長の棒グラフを描くために、リストB.1のスクリプトを作成した。
リストB.1 簡単な棒グラフ作成スクリプト(simple.py)
import
matplotlib.pyplot as plt
import
japanize_matplotlib
# 日本語表示用モジュール
plt.bar(['男性', '女性'],
[171.5, 157.5])
plt.show()
棒グラフ描画コードは次の1行である。
plt.bar(['男性', '女性'],
[171.5, 157.5])
関数plt.barの第1パラメータに、棒グラフのバーに対するラベル['男性', '女性']を指定し、第2パラメータに各バーの値[171.5, 157.5]を指定している。
描かれたグラフは、スクリプト
plt.show()
の実行で表示される。
グラフでは、日本語による表記が行われるので、そのためのモジュールを次のコードでimportしている。
import japanize_matplotlib
このモジュールは、次のコマンドでインストールできる。
pip install
japanize_matplotlib
リストB.1を実行すると、図B.2のグラフが表示される。
図B.2
表示されたグラフは、保存ボタンをクリックしてファイルに保存することができる。
図B.2のグラフに説明を加えたり、デフォルトの設定値を変更したりするために、リストB.2のスクリプトを作成した。
リストB.2 棒グラフの描画:詳細設定版(described_bar.py)
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('身長.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
print('csv_data =\n', csv_data)
names = [v for v in
csv_data.keys()] # キーのリスト
print('names =\n', names)
data = csv_data.values
# データのndarray
print('data =\n', data)
plt.title('身長:20歳〜29歳', fontsize = 20)
cntnr = plt.bar(names[1:],
data[0][1:],
# バーの名前と値
color = ['lime', 'aqua'],
# バーの色
edgecolor = 'k',
# バーの枠の色
width = 0.5,
# バーの幅
linewidth = 3,
# バーの枠の線幅
yerr
= data[1][1:], capsize = 20, # エラーバーの長さ(標準偏差)とキャップの長さ
error_kw ={'linewidth':10},
# エラーバーの線幅
ecolor='r')
# エラーバーの色
# 上で作成した棒グラフの情報cntnrのバーにラベルを付ける
plt.bar_label(cntnr, [f'{v}' for v in
data[0][1:]],
label_type = 'center', fontsize = 20)
plt.xticks(fontsize = 20)
plt.yticks(fontsize = 14)
plt.show()
リストB.2を実行すると、図B.3のグラフが表示される。
図B.3
リストB.2では、次のスクリプトで図B.1のCSVファイル身長.csvを読み込んでいる。
with open('身長.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
読み込まれたファイルの内容を、次のスクリプトで書き出している。
print('csv_data =\n', csv_data)
names = [v for v in
csv_data.keys()] # キーのリスト
print('names =\n', names)
data = csv_data.values
# データのndarray
print('data =\n', data)
出力は、以下のようである。
csv_data =
項目 男性 女性
0 身長 171.5 157.5
1
標準偏差 6.6 5.5
names =
['項目', '男性', '女性']
data =
[['身長' 171.5 157.5]
['標準偏差' 6.6 5.5]]
リストB.2では、グラフの上部に表示する文字列をplt.titleで設定している。
plt.title('身長:20歳〜29歳', fontsize = 20)
cntnr = plt.bar(names[1:],
data[0][1:],
# バーの名前と値
color = ['lime', 'aqua'],
# バーの色
edgecolor = 'k',
# バーの枠の色
width = 0.5,
# バーの幅
linewidth = 3,
# バーの枠の線幅
yerr
= data[1][1:], capsize = 20, # エラーバーの長さ(標準偏差)とキャップの長さ
error_kw ={'linewidth':10},
# エラーバーの線幅
ecolor='r')
# エラーバーの色
関数plt.barのパラメータで、グラフの設定をいろいろ行っている。
関数の戻り値を
cntnr = plt.bar(…)
と識別子cntnrで保存しているのは、次のコードで使うためである。
Pythonでは、
識別子 = オブジェクト
の文は、左辺への代入ではなく、左辺の識別子を右辺のオブジェクトを指し示すものにするということであるが、簡単に「代入」というような言い方をすることが多い。
色の指定はいろいろなものが用意されているが、次のウェブサイトを参照されたい。
https://matplotlib.org/stable/gallery/color/named_colors.html
RGBで直接指定する例は、岡本(2019)のp.17にある
次のスクリプトは、バー内に文字列を表示するものである。
plt.bar_label(cntnr, [f'{v}' for v in
data[0][1:]],
label_type
= 'center', fontsize = 20)
東京都の2022年各月のデータを気象庁のホームページよりダウンロード(2023.11.25)したものから、平均気温、最高気温、最低気温を抜粋して図L.1のCSVファイルのようにまとめた。
図L.1 東京2022年(気象庁サイトよりダウンロード抜粋)
平均気温の折れ線を描くために、リストL.1のスクリプトを作成した。
リストL.1 簡単な折れ線グラフ描画スクリプト(simple.py)
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('Tokyo2022.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
print('csv_data =\n', csv_data)
means = csv_data['平均気温'].values # 平均気温データの取り出し
print('means =\n', means)
months = ['1月','2月','3月','4月','5月','6月',
'7月','8月','9月','10月','11月','12月']
plt.plot(months, means)
# 折れ線のプロット
plt.show()
図L.1のデータファイルTokyo2022.csvを次のスクリプトでcsv_dataに読み込んでいる。
with open('Tokyo2022.csv', 'r') as f:
csv_data = pd.read_csv(f)
読み込んだファイルから、次のスクリプトで平均気温を取り出している。
means = csv_data['平均気温'].values # 平均気温データの取り出し
print('means =\n', means)
上のスクリプトを実行すると、次の出力が表示される。
means =
[ 4.9 5.2 10.9 15.3 18.8 23. 27.4 27.5 24.4 17.2 14.5 7.5]
横軸(X軸)のデータのラベルをmonthsに設定して、次のスクリプトで折れ線を描いている。
months = ['1月','2月','3月','4月','5月','6月',
'7月','8月','9月','10月','11月','12月']
plt.plot(months, means)
# 折れ線のプロット
リストL.1のスクリプトを実行すると、図L.2の折れ線グラフが表示される。
図L.2
図L.2は平均気温のみの折れ線であるが、これに最低気温と最高気温の折れ線も加えてみる。
図L.3
図L.3のグラフは、次のリストL.2のスクリプトで描いている。
リスト」L.2 平均気温、最高気温、最低気温の折れ線グラフ描画スクリプト(described.py)
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('Tokyo2022.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
means = csv_data['平均気温'].values
print('means =\n', means)
maxs = csv_data['最高気温'].values
print('maximums =\n', maxs)
mins = csv_data['最低気温'].values
print('minimums =\n', mins)
plt.title('東京の気温(2022年)', fontsize = 24)
months = [f'{v}月' for v in range(1,13)]
plt.plot(months, maxs, 'r', linewidth
= 2, label = '最高気温')
plt.plot(months, means, 'k', linewidth
= 3, label = '平均気温')
plt.plot(months, mins, 'cyan',
linewidth = 2, label = '最低気温')
plt.hlines(0, '1月', '12月',
linestyle = '--', color = 'cyan')
plt.hlines(35, '1月', '12月',
linestyle = '--', color = 'r')
plt.ylabel('℃', fontsize = 16)
plt.legend()
plt.show()
まず、図L.1のCSVファイルを読み込んでいる。
with open('Tokyo2022.csv', 'r') as f:
csv_data =
pd.read_csv(f)
DataFrame csv_data から、平均値、最高気温、最低気温を取り出してmeans、maxs、minsに設定している。
maxs
means = csv_data['平均気温'].values
print('means =\n', means)
maxs = csv_data['最高気温'].values
print('maximums =\n', maxs)
mins = csv_data['最低気温'].values
print('minimums =\n', mins)
上のスクリプトを実行すると、端末には以下の出力が表示される。
means =
[ 4.9 5.2 10.9 15.3 18.8 23. 27.4 27.5 24.4 17.2 14.5 7.5]
maximums =
[13.4 18.5 24.1 27.7 31.2 36.4 37. 36.4 32.7 29.6 24.3 15.9]
minimums =
[-3.5 -1.9 0.5
3.6 9.3 14.7 21.8 18.6
16.5 8.5 7.7 -0.1]
グラフのタイトルと横軸に表示する文字列を、次のスクリプトで設定している。
plt.title('東京の気温(2022年)', fontsize = 24)
months = [f'{v}月' for v in range(1,13)]
3本の折れ線は、次のスクリプトで描いている。
plt.plot(months, maxs, 'r', linewidth
= 2, label = '最高気温')
plt.plot(months, means, 'k', linewidth
= 3, label = '平均気温')
plt.plot(months, mins, 'cyan',
linewidth = 2, label = '最低気温')
折れ線の色は、「'r'」などの名前で指定している。色の名前については、次のウェブサイトに説明がある。
https://matplotlib.org/stable/gallery/color/named_colors.html
色は、RGBでも指定できるが、岡本(2019)、p.17を参照されたい。
図L.3では、0℃と35℃の位置に関数plt.hlinesによって破線が水平に引かれている。
plt.hlines(0, '1月', '12月',
linestyle = '--', color = 'cyan')
plt.hlines(35, '1月', '12月',
linestyle = '--', color = 'r')
線のスタイルlinestyleについては、次のウェブサイトに説明がある。
https://matplotlib.org/stable/gallery/lines_bars_and_markers/linestyles.html
岡本(2019)、pp.22-26でも説明している。
関数plt.plot()などでパラメータlabelが指定されている場合は、関数
plt.legend()
の実行で表示される。表示される場所は、自動で決まるが、パラメータlocで指定することもできる。パラメータlocの値と表示位置の関係は、ウェブサイト
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html
を参照されたい。岡本(2019)のpp.17-18でも説明している。
気象庁のホームページから気象データをダウンロードして(2023.11.27、20時ごろ)、全国の観測地点における最高気温と最低気温を取り出して図H.1のようにまとめた。
図H.1a
図H.1b
図H.1のファイル最高最低気温20231127.csvを読み込み、最高気温のヒストグラムを描くスクリプトを、リストH.1のように作成した。
リストH.1 最高気温のヒストグラム描画スクリプト(simple.py)
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('最高最低気温20231127.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
maxs = csv_data['最高気温'].values # キー「最高気温」のデータ
plt.hist(maxs)
# バーグラフの描画
plt.show()
リストH.1のスクリプトを実行すると、図H.2のヒストグラムが描画される。
図H.2
図H.2のヒストグラムでは、bin(階級、級)が自動的に決められるので、階級の設定が必ずしも適切であるとは限らない。
これに対して、次のリストH.2のスクリプトでは、binの境界値が指定されており、軸のラベルなども設定されていて、グラフから情報を読み取り易い。
リストH.2 階級の境界値が指定されたヒストグラム(bins_given.py)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('最高最低気温20231127.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
maxs = csv_data['最高気温'].values
# キー「最高気温」のデータの取り出し
print('min_v =', np.min(maxs), ' max_v =', np.max(maxs))
v_bins = np.arange(-5, 31, 5)
# bin境界値の設定
print('v_bins =\n', v_bins)
results = plt.hist(maxs, bins =
v_bins)
# ヒストグラムの描画
plt.title('最高気温', fontsize=20)
plt.xlabel('℃', fontsize=14)
plt.ylabel('度数', fontsize=14)
plt.show()
print('results =\n', results)
# bin情報の出力
リストH.2のスクリプトを実行すると、図H.3のヒストグラムが描かれる。
図H.3
最高気温の最低値は−0.6、最高値は27.2であるので、階級の境界値を−5から始めて、5間隔で30までとしている。すなわち、
v_bins = np.arange(-5, 31, 5)
# bin境界値の設定
print('v_bins =\n', v_bins)
である。上のスクリプトを実行すると、次の出力を得る。
v_bins =
[-5
0 5 10 15 20 25 30]
上の階級の境界値を用いて、次のスクリプトでヒストグラムを描いている。
results =
plt.hist(maxs, bins = v_bins)
関数の戻り値resultsには、階級の情報が格納されている。
次のスクリプト
print('results
=\n', results)
を実行すると、以下の出力を得る。
results =
(array([ 1., 118., 151., 232., 340., 47., 26.]), array([-5., 0.,
5., 10., 15., 20., 25., 30.]), <BarContainer object of 7 artists>)
最初のリストに各階級の度数が、2番目のリストに階級の境界値が示されている。
グラフのタイトルと軸のラベルが次のスクリプトで設定されている。
plt.title('最高気温', fontsize=20)
plt.xlabel('℃', fontsize=14)
plt.ylabel('度数', fontsize=14)
最高気温と最低気温のグラフを同時に表示することを考える(図H.4)。
図H.4
図H.4のグラフは、リストH.3のスクリプトで描いたものである。
リストH.3 最高気温と最低気温のヒストグラムの同時表示(mixed.py)。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('最高最低気温20231127.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
maxs = csv_data['最高気温'].values # キー「最高気温」データの取り出し
mins = csv_data['最低気温'].values # キー「最低気温」データの取り出し
print('min(maxs) =', np.min(maxs),
' max(maxs) =', np.max(maxs))
print('min(mins) =', np.min(mins),
' max(mins) =', np.min(mins))
v_bins = np.arange(-15, 31, 5)
print('v_bins =\n', v_bins)
plt.title('最高気温と最低気温', fontsize=16)
results = plt.hist(
# bin情報をresultsに返す
[maxs, mins],
# 表示データのリスト
label = ['最高気温', '最低気温'], # 表示データラベルのリスト
color = ['orange', 'b'],
# 表示データの色
bins = v_bins)
# binの境界値のリスト
plt.xlabel('℃', fontsize=16)
plt.ylabel('度数', fontsize=16)
plt.legend(fontsize=14)
# ラベルの表示
plt.show()
print('results =\n', results)
# resultsの出力
複数のヒストグラムの同時提示は、それぞれのデータなどをリストとして設定することにより描くことができる。
results =
plt.hist(
# bin情報をresultsに返す
[maxs, mins],
# 表示データのリスト
label = ['最高気温', '最低気温'], # 表示データラベルのリスト
color = ['orange', 'b'],
# 表示データの色
bins = v_bins)
# binの境界値のリスト
2つのヒストグラムを別のグラフとして描くこともできる(図H.5)。
図H.5
図H.5のグラフは、リストH.4のスクリプトで描かれている。
リストH.4 2つのグラフを縦に並べて表示(two_hist.py)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('最高最低気温20231127.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
maxs = csv_data['最高気温'].values
print('maxs =\n', maxs[:5], maxs[-5:])
print('min(maxs) =', np.min(maxs),
' max(maxs) =', np.max(maxs))
mins = csv_data['最低気温'].values
print('mins =\n', mins[:5], mins[-5:])
print('min(mins) =',
np.min(mins),' max{mins) =',
np.max(mins))
v_bins = np.arange(-15,31,5)
plt.figure(figsize = (5,7))
# 描画画面のサイズ、縦長
ax1 = plt.subplot(2, 1, 1)
# 描画画面を2行1列に区切った1番目の領域
ax1.set_title('最高気温', fontsize=20)
ax1.set_xlabel('℃', fontsize=16)
ax1.set_ylabel('度数', fontsize=16)
results1=ax1.hist(maxs, bins=v_bins,
color = 'orange')
ax1.plot([], 's', c = 'orange', label
= '最高気温') # 空リストは何も表示しない
ax1.legend(fontsize = 16)
ax2 = plt.subplot(212, sharex =
ax1) # 描画画面を2行1列に区切った2番目の領域
ax2.set_title('最低気温', fontsize=20)
ax2.set_xlabel('℃', fontsize=16)
ax2.set_ylabel('度数', fontsize=16)
results2=ax2.hist(mins, bins = v_bins,
color = 'cyan')
ax2.plot([], 's', c = 'cyan', label='最低気温')
plt.legend(fontsize=16)
plt.tight_layout()
# 描画画面内に納まるように調整
plt.show()
print('results1 =\n', results1)
print('results2 =\n', results2)
次のスクリプトで、描画画面全体の大きさを設定している。
plt.figure(figsize = (5,7))
次のスクリプト
ax1 =
plt.subplot(2, 1, 1)
は、画面を2行1列の領域に分け、1番目の領域の座標系をax1とするものである。描画領域は、左上から右方向に行単位で数え1から始まる自然数である。
次のスクリプトでは、画面を2行1列に分けて、2つ目の領域をax2で表すものである。
ax2 =
plt.subplot(212, sharex = ax1)
パラメータsharex = ax1により、座標系ax2は座標系ax1とX軸の座標が共通であると設定している。
グラフを横に並べた場合が、図H.6である。
図H.6
図H.6のグラフは、リストH.5のスクリプトで描かれている。
リストH.5 グラフを縦に並べた場合(two_hist_h.py)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('最高最低気温20231127.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
print('csv_data =\n', csv_data)
names = [v for v in
csv_data.keys()] # キーのリスト
print('names =\n', names)
data = csv_data.values
# データのndarray
print('data =\n', data)
maxs = csv_data['最高気温'].values
print('maxs =\n', maxs[:5], maxs[-5:])
print('min(maxs) =', np.min(maxs),
' max(maxs) =', np.max(maxs))
mins = csv_data['最低気温'].values
print('mins =\n', mins[:5], mins[-5:])
print('min(mins) =',
np.min(mins),' max{mins) =',
np.max(mins))
v_bins = np.arange(-15,31,5)
plt.figure(figsize = (7,5))
fig, (ax1, ax2) = plt.subplots(1,2,
sharey=True)
fig.suptitle('2023年11月27日の気温', fontsize=20)
ax1.set_title('最低気温', fontsize=18)
ax1.set_ylabel('℃', fontsize=16)
ax1.set_xlabel('度数', fontsize=16)
results2=ax1.hist(mins, bins = v_bins,
orientation = 'horizontal',
color = 'cyan')
ax1.plot([], 's', c = 'cyan', label='最低気温')
ax1.legend(fontsize=16)
ax2.set_title('最高気温', fontsize=18)
ax2.set_xlabel('度数', fontsize=16)
results1=ax2.hist(maxs, bins=v_bins,
orientation = 'horizontal', color = 'orange')
ax2.plot([], 's', c = 'orange', label
= '最高気温')
ax2.legend(fontsize = 16)
fig.tight_layout()
fig.show()
print('results1 =\n', results1)
print('results2 =\n', results2)
リストH.5では、次のスクリプトで描画画面を1行2列に分け、それぞれを座標系ax1とax2で表している。
fig, (ax1, ax2) = plt.subplots(1,2,
sharey=True)
fig.suptitle('2023年11月27日の気温', fontsize=20)
パラメタsharey=Trueの指定により、2つのグラフのY軸座標は共通である。
画面の図全体を表すfigのsuptitleにより、図全体のタイトルが設定されている。
最高気温と最低気温のデータ(図H.1)の散布図を描いてみるために、リストS.1のスクリプトを用意した。
リストS.1 散布図描画の簡単なスクリプト(simple_scatter.py)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('最高最低気温20231127.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
maxs = csv_data['最高気温'].values
mins = csv_data['最低気温'].values
plt.scatter(mins, maxs)
# 散布図の描画
plt.xlabel('最低気温', fontsize=16)
plt.ylabel('最高気温', fontsize=16)
plt.show()
リストS.1のスクリプトを実行すると、図S.1の散布図が描かれる。
図S.1
散布図に、それぞれの変数、最低気温と最高気温、のヒストグラムも付け加えるために、リストS.2のスクリプトを作成した。
リストS.2 散布図とヒストグラムの描画(scatter_hist.py)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 日本語表示用モジュール
with open('最高最低気温20231127.csv', 'r') as f:
csv_data =
pd.read_csv(f)
# CSVファイルの読み込み
maxs = csv_data['最高気温'].values
mins = csv_data['最低気温'].values
# 描画画面の作成
fig = plt.figure(figsize=(7,7))
# 描画画面を3行3列のグリッドとして、
# 0行目、0列目から2行1列の領域を、座標ax1とする
ax1 = plt.subplot2grid((3,3), (0,0),
rowspan=2, colspan=1,)
# 描画画面を3行3列のグリッドとして、
# 0行目、1列目から2行2列の領域を、座標ax2とする
# Y座標はax1と共通とする
ax2 = plt.subplot2grid((3,3), (0,1), rowspan=2,
colspan=2, sharey=ax1)
# 描画画面を3行3列のグリッドとして、
# 2行目、1列目から1行2列の領域を、座標ax3とする
# X座標はax2と共通とする
ax3 = plt.subplot2grid((3,3), (2,1),
rowspan=1, colspan=2, sharex = ax2)
ax1.hist(maxs,
orientation='horizontal', bins=np.arange(-5, 31, 5))
ax2.plot(mins, maxs, marker='o',
linewidth=0, fillstyle='none')
ax2.set_xlabel('最低気温', fontsize=16)
ax2.set_ylabel('最高気温', fontsize=16)
ax3.hist(mins, bins=np.arange(-15, 26,
5))
fig.suptitle('最低気温と最高気温', fontsize=20)
fig.tight_layout()
fig.show()
リストS.2のスクリプトを実行すると、図S.2のグラフが描かれる。
図S.2
図S.2の散布図では、点は中空の丸で描かれている。中空のマーカーで描くために、関数scatterではなく、関数plotによる描画を行っている。
ax2.plot(mins, maxs, marker='o',
linewidth=0, fillstyle='none')
マーカーとしてパラメータmarker='o'により丸を指定して、中空にするためにパラメータfillstyle='none'を設定している。点と点の間の線分の描画を避けるためにパラメータlinewidth=0を設定して線の太さを0としている。
画面の作成において、画面全体を表す変数figを用意している。
# 描画画面の作成
fig = plt.figure(figsize=(7,7))
この変数figを用いて、グラフ全体のタイトル、グラフの整列、グラフ表示を行っている。
fig.suptitle('最低気温と最高気温', fontsize=20)
fig.tight_layout()
fig.show()
PythonのモジュールMatplotlibには、グラフ描画関係の関数がいろいろ用意されている。ウェブサイト
https://matplotlib.org/3.5.3/api/_as_gen/matplotlib.pyplot.html
を参照されたい。
グラフ描画におけるマーカー、色などの設定のサンプルとして、図M.1を描いてみた。
図M.1
スクリプトは、リストM.1に示すものである。
リストM.1 マーカー、色などの設定例(marker_color.py)
import matplotlib.pyplot as plt
"""
背景色が黒の描画画面の作成
"""
plt.figure(figsize=(7,7),
facecolor='k')
"""
座標内を青に設定
"""
ax = plt.axes()
ax.set_facecolor('b')
"""
座標の枠を黄色の線で表示
描画領域の基準位置として使用
"""
plt.plot([0,1,1,0,0], [0,0,1,1,0],
'y')
"""
大きな白い円盤の表示
色をRGB'#FFFFFF'で設定している
"""
plt.scatter(0.5, 0.7, marker='o',
s=5000, c='#FFFFFF')
"""
rcParamsによりマーカーの枠の色と枠の太さを設定
"""
plt.rc('lines', markeredgecolor='g',
markeredgewidth=10)
"""
2つの上向き三角形の点の描画
linewidth=0と設定して2つの点の間の線分の描画を無効にしている
"""
plt.plot([0.25, 0.75], [0.2, 0.2],
c='cyan', marker='^', markersize=100,
linewidth=0)
"""
rcParamsをデフォルト値に戻す
"""
plt.rcdefaults()
"""
星印の描画
"""
plt.scatter(0.5, 0.4, marker='*', s =
1000, c = 'orange')
plt.scatter([0.2, 0.8], [0.8, 0.8],
marker='*', c='y', s=200)
"""
茶色の太い線を引いてから、上から黒の点線を描画
"""
plt.plot([0,1],[0.01,0.01], c =
'saddlebrown', linewidth=20)
plt.plot([0,1],[0.01,0.01], c = 'k',
linestyle=(0,(0.1,1)), linewidth=20)
plt.show()