3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【データサイエンティスト入門】記述統計と単回帰分析♬

Last updated at Posted at 2020-08-24

昨夜で、【データサイエンティスト入門】科学計算、データ加工、グラフ描画ライブラリの使い方の基礎までまとめました。今夜からいよいよそれらを使って本題に入っていきます。今夜は記述統計と単回帰分析をまとめます。本書に乗った解説を補足することとします。
【注意】
「東京大学のデータサイエンティスト育成講座」を読んで、ちょっと疑問を持ったところや有用だと感じた部分をまとめて行こうと思う。
したがって、あらすじはまんまになると思うが内容は本書とは関係ないと思って読んでいただきたい。
###Chapter 3 記述統計と単回帰分析
####Chapter 3-1 統計解析の種類
#####3-1-1 記述統計と推論統計
統計解析の手法は、記述統計と推論統計に分かれる。
######3-1-1-1 記述統計
「集めたデータの特徴をつかんだり分かり易く整理したり見やすくしたりする方法。平均、標準偏差などを計算してデータの特徴を計算したり、データを分類したり、図やグラフを用いて表現したりするのが、記述統計です。」
######3-1-1-2 推論統計
「部分的なデータしかないものから、確率分布に基いたモデルを用いて精密な解析をし、全体を推論して統計を求めるのが推論統計の考え方です。」
「過去のデータから未来予測するときにも使われます。この章では、推論統計の基礎である単回帰分析について説明します。より複雑な推論統計については、次の4章で扱います。」
#####3-1-2 ライブラリのインポート

import numpy as np
import scipy as sp
import pandas as pd
from pandas import Series, DataFrame

import matplotlib as mpl
import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

from sklearn import linear_model

sklearnを以下でインストールします。


$ sudo pip3 install scikit-learn

以下のとおり、Rasipi4でも使えそうです。

 $ python3
Python 3.7.3 (default, Jul 25 2020, 13:03:44) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from sklearn import linear_model 
>>> 

一応、python3-sklearn-docが見つかりませんでしたがDebian/Ubuntuの以下でもインストール出来たようです。

$ sudo apt-get install python3-sklearn python3-sklearn-lib

※検証は以下単回帰分析のとき問題でるかを見ていきます
####Chapter 3-2 データの読込と対話
...省略
######3-2-1-5
以下のサイトから、以下のプログラムでデータstudent.zipを取得します。
https://archive.ics.uci.edu/ml/machine-learning-databases/00356/student.zip

import requests, zipfile
from io import StringIO
import io

url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00356/student.zip'
r = requests.get(url, stream = True)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall()

以下の4つのファイルが展開されました。
student.txt
student-mat.csv
student-merge.R
student-pcr.csv
#####3-2-2 データ読み込みと確認
上記importにつなげて、以下を実行

student_data_math = pd.read_csv('./chap3/student-mat.csv')
print(student_data_math.head())

データが ;区切りを確認できる。

school;sex;age;address;famsize;Pstatus;Medu;Fedu;Mjob;Fjob;reason;guardian;traveltime;studytime;failures;schoolsup;famsup;paid;activities;nursery;higher;internet;romantic;famrel;freetime;goout;Dalc;Walc;health;absences;G1;G2;G3
0  GP;"F";18;"U";"GT3";"A";4;4;"at_home";"teacher...                                                                                                                                                                              
1  GP;"F";17;"U";"GT3";"T";1;1;"at_home";"other";...                                                                                                                                                                              
2  GP;"F";15;"U";"LE3";"T";1;1;"at_home";"other";...                                                                                                                                                                              
3  GP;"F";15;"U";"GT3";"T";4;2;"health";"services...                                                                                                                                                                              
4  GP;"F";16;"U";"GT3";"T";3;3;"other";"other";"h... 

読込を ;に変更して再読み込み。

student_data_math = pd.read_csv('./chap3/student-mat.csv', sep =';')
print(student_data_math.head())

綺麗に見えた。

  school sex  age address famsize Pstatus  Medu  Fedu  ... goout Dalc Walc health  absences  G1  G2  G3
0     GP   F   18       U     GT3       A     4     4  ...     4    1    1      3         6   5   6   6
1     GP   F   17       U     GT3       T     1     1  ...     3    1    1      3         4   5   5   6
2     GP   F   15       U     LE3       T     1     1  ...     2    2    3      3        10   7   8  10
3     GP   F   15       U     GT3       T     4     2  ...     2    1    1      5         2  15  14  15
4     GP   F   16       U     GT3       T     3     3  ...     2    1    2      5         4   6  10  10

[5 rows x 33 columns]

#####3-2-3 データの性質を確認する
print(student_data_math.info())

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 395 entries, 0 to 394
Data columns (total 33 columns):
 #   Column      Non-Null Count  Dtype
---  ------      --------------  -----
 0   school      395 non-null    object
 1   sex         395 non-null    object
 2   age         395 non-null    int64
 3   address     395 non-null    object
 4   famsize     395 non-null    object
 5   Pstatus     395 non-null    object
 6   Medu        395 non-null    int64
 7   Fedu        395 non-null    int64
 8   Mjob        395 non-null    object
 9   Fjob        395 non-null    object
 10  reason      395 non-null    object
 11  guardian    395 non-null    object
 12  traveltime  395 non-null    int64
 13  studytime   395 non-null    int64
 14  failures    395 non-null    int64
 15  schoolsup   395 non-null    object
 16  famsup      395 non-null    object
 17  paid        395 non-null    object
 18  activities  395 non-null    object
 19  nursery     395 non-null    object
 20  higher      395 non-null    object
 21  internet    395 non-null    object
 22  romantic    395 non-null    object
 23  famrel      395 non-null    int64
 24  freetime    395 non-null    int64
 25  goout       395 non-null    int64
 26  Dalc        395 non-null    int64
 27  Walc        395 non-null    int64
 28  health      395 non-null    int64
 29  absences    395 non-null    int64
 30  G1          395 non-null    int64
 31  G2          395 non-null    int64
 32  G3          395 non-null    int64
dtypes: int64(16), object(17)
memory usage: 102.0+ KB

cat student.txtして、中身を見るとこのデータは以下のような内容だそうです。
※本書では翻訳されています

$ cat student.txt
# Attributes for both student-mat.csv (Math course) and student-por.csv (Portuguese language course) datasets:
1 school - student's school (binary: "GP" - Gabriel Pereira or "MS" - Mousinho da Silveira)
2 sex - student's sex (binary: "F" - female or "M" - male)
3 age - student's age (numeric: from 15 to 22)
4 address - student's home address type (binary: "U" - urban or "R" - rural)
5 famsize - family size (binary: "LE3" - less or equal to 3 or "GT3" - greater than 3)
6 Pstatus - parent's cohabitation status (binary: "T" - living together or "A" - apart)
7 Medu - mother's education (numeric: 0 - none,  1 - primary education (4th grade), 2 – 5th to 9th grade, 3 – secondary education or 4 – higher education)
8 Fedu - father's education (numeric: 0 - none,  1 - primary education (4th grade), 2 – 5th to 9th grade, 3 – secondary education or 4 – higher education)
9 Mjob - mother's job (nominal: "teacher", "health" care related, civil "services" (e.g. administrative or police), "at_home" or "other")
10 Fjob - father's job (nominal: "teacher", "health" care related, civil "services" (e.g. administrative or police), "at_home" or "other")
11 reason - reason to choose this school (nominal: close to "home", school "reputation", "course" preference or "other")
12 guardian - student's guardian (nominal: "mother", "father" or "other")
13 traveltime - home to school travel time (numeric: 1 - <15 min., 2 - 15 to 30 min., 3 - 30 min. to 1 hour, or 4 - >1 hour)
14 studytime - weekly study time (numeric: 1 - <2 hours, 2 - 2 to 5 hours, 3 - 5 to 10 hours, or 4 - >10 hours)
15 failures - number of past class failures (numeric: n if 1<=n<3, else 4)
16 schoolsup - extra educational support (binary: yes or no)
17 famsup - family educational support (binary: yes or no)
18 paid - extra paid classes within the course subject (Math or Portuguese) (binary: yes or no)
19 activities - extra-curricular activities (binary: yes or no)
20 nursery - attended nursery school (binary: yes or no)
21 higher - wants to take higher education (binary: yes or no)
22 internet - Internet access at home (binary: yes or no)
23 romantic - with a romantic relationship (binary: yes or no)
24 famrel - quality of family relationships (numeric: from 1 - very bad to 5 - excellent)
25 freetime - free time after school (numeric: from 1 - very low to 5 - very high)
26 goout - going out with friends (numeric: from 1 - very low to 5 - very high)
27 Dalc - workday alcohol consumption (numeric: from 1 - very low to 5 - very high)
28 Walc - weekend alcohol consumption (numeric: from 1 - very low to 5 - very high)
29 health - current health status (numeric: from 1 - very bad to 5 - very good)
30 absences - number of school absences (numeric: from 0 to 93)

# these grades are related with the course subject, Math or Portuguese:
31 G1 - first period grade (numeric: from 0 to 20)
31 G2 - second period grade (numeric: from 0 to 20)
32 G3 - final grade (numeric: from 0 to 20, output target)

Additional note: there are several (382) students that belong to both datasets . 
These students can be identified by searching for identical attributes
that characterize each student, as shown in the annexed R file.

#####3-2-4 量的データと質的データ
・量的データ
四則演算を適用可能な連続値で表現されるデータであり、比率に意味がある。例;人数、金額など
・質的データ
四則演算を適用不可能な不連続のデータであり、状態を表現するために利用される。
例;順位、カテゴリなど

性別は質的データ

print(student_data_math['sex'].head())
0    F
1    F
2    F
3    F
4    F
Name: sex, dtype: object

欠席数は量的データ

print(student_data_math['absences'].head())
0     6
1     4
2    10
3     2
4     4
Name: absences, dtype: int64

#####3-2-4-2 軸別に平均値を求める

print(student_data_math.groupby('sex')['age'].mean())
sex
F    16.730769
M    16.657754
Name: age, dtype: float64

女性の方が勉強する。

print(student_data_math.groupby('sex')['studytime'].mean())
sex
F    2.278846
M    1.764706
Name: studytime, dtype: float64

####記述統計
#####3-3-1 ヒストグラム

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
y1 = student_data_math['absences']
ax1.hist(y1, bins = 10, range =(0.0,max(y1)))
ax1.set_ylabel('count')
ax1.set_xlabel('absences')
plt.grid(True)
plt.show()

Figure_13absences.png
#####3-3-2 平均値、中央値、最頻値

print('平均値{}'.format(student_data_math['absences'].mean()))
print('中央値{}'.format(student_data_math['absences'].median()))
print('最頻値{}'.format(student_data_math['absences'].mode()))

平均値5.708860759493671
中央値4.0
最頻値0    0
dtype: int64

図で検証するために、上記を図を拡大して記入します。
※横軸0.5修正しています。

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
y1 = student_data_math['absences']
ax1.hist(y1, bins = 30, range =(0.0,30))  #,max(y1)
x0 = student_data_math['absences'].mean()
ax1.plot(x0+0.5, 70,  'red', marker = 'o',markersize=10,label ='mean')
x0 = student_data_math['absences'].median()
ax1.plot(x0+0.5, 70, 'blue', marker = 'o',markersize=10,label ='median')
x0 = student_data_math['absences'].mode()
ax1.plot(x0+0.5, 70, 'black', marker = 'o',markersize=10,label ='mode')
ax1.legend()
ax1.set_ylabel('count')
ax1.set_xlabel('absences')
plt.grid(True)
plt.show()

Figure_13absences30m-.png
#####3-3-3 分散と標準偏差
定義式
分散$σ^2$

σ^2 = \frac{1}{n}\Sigma_{i=1}^{n}(x_i-\bar{x})^2

標準偏差$σ$
std(standered deviation)

σ = \sqrt{\frac{1}{n}\Sigma_{i=1}^{n}(x_i-\bar{x})^2}
print('分散{}'.format(student_data_math['absences'].var(ddof=0)))
print('標準偏差{}'.format(student_data_math['absences'].std(ddof = 0)))
print('標準偏差{}'.format(np.sqrt(student_data_math['absences'].var())))
分散63.887389841371565
標準偏差7.99295876640006
標準偏差8.00309568710818

平均±標準偏差をプロットする。

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
y1 = student_data_math['absences']
ax1.hist(y1, bins = 30, range =(0.0,30))  #,max(y1)
x0 = student_data_math['absences'].mean()
ax1.plot(x0+0.5, 70,  'red', marker = 'o',markersize=10,label ='mean')
x1 = student_data_math['absences'].std(ddof=0)
ax1.plot(x0+x1+0.5, 70, 'blue', marker = 'o',markersize=10,label ='mean+std')
ax1.plot(x0-x1+0.5, 70, 'black', marker = 'o',markersize=10,label ='mean-std')
ax1.legend()
ax1.set_ylabel('count')
ax1.set_xlabel('absences')
plt.grid(True)
plt.show()

Figure_13absences30m-std.png
#####3-3-4 要約統計量とパーセンタイル値
パーセンタイル値は全体数を100とした時の順位
25番目を25パーセンタイル、第一四分位点
75番目を75パーセンタイル、第三四分位点
50パーセンタイル値、中央値

print('要約統計量', student_data_math['absences'].describe())
要約統計量 count    395.000000
mean       5.708861
std        8.003096
min        0.000000
25%        0.000000
50%        4.000000
75%        8.000000
max       75.000000
Name: absences, dtype: float64

#####四分位範囲を求める
25パーセンタイル;describe(4)
75パーセンタイル:describe(6)
差;describe(6)-describe(4)
print('75-25パーセンタイル', student_data_math['absences'].describe()[6]-student_data_math['absences'].describe()[4])
75-25パーセンタイル 8.0

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
y1 = student_data_math['absences']
ax1.hist(y1, bins = 30, range =(0.0,30))  #,max(y1)
x0 = student_data_math['absences'].median()
ax1.plot(x0+0.5, 70,  'red', marker = 'o',markersize=10,label ='median')
x1 = student_data_math['absences'].describe()[4]
ax1.plot(x1+0.5, 70, 'blue', marker = 'o',markersize=10,label ='25percentile')
x1 = student_data_math['absences'].describe()[6]
ax1.plot(x1+0.5, 70, 'black', marker = 'o',markersize=10,label ='75percentile')
ax1.legend()
ax1.set_ylabel('count')
ax1.set_xlabel('absences')
plt.grid(True)
plt.show()

Figure_13absences30mpp.png
#####3-3-4-2 全列のdescribe()

print('全列要約統計量', student_data_math.describe())
全列要約統計量
              age        Medu        Fedu  traveltime  ...    absences          G1          G2          G3
count  395.000000  395.000000  395.000000  395.000000  ...  395.000000  395.000000  395.000000  395.000000
mean    16.696203    2.749367    2.521519    1.448101  ...    5.708861   10.908861   10.713924   10.415190
std      1.276043    1.094735    1.088201    0.697505  ...    8.003096    3.319195    3.761505    4.581443
min     15.000000    0.000000    0.000000    1.000000  ...    0.000000    3.000000    0.000000    0.000000
25%     16.000000    2.000000    2.000000    1.000000  ...    0.000000    8.000000    9.000000    8.000000
50%     17.000000    3.000000    2.000000    1.000000  ...    4.000000   11.000000   11.000000   11.000000
75%     18.000000    4.000000    3.000000    2.000000  ...    8.000000   13.000000   13.000000   14.000000
max     22.000000    4.000000    4.000000    4.000000  ...   75.000000   19.000000   19.000000   20.000000

[8 rows x 16 columns]

####3-3-5 箱ひげ図
箱ひげ図は、(最小値,第1四分位点,中央値,第3四分位点,最大値)で以下のように箱とひげで表す手法。

fig, (ax1,ax2) = plt.subplots(2, 1, figsize=(8,2*4))
y1 = student_data_math['G1']
ax1.hist(y1, bins = 30, range =(0.0,max(y1)))  #,max(y1)
x0 = student_data_math['G1'].median()
ax1.plot(x0+0.5, 60,  'red', marker = 'o',markersize=10,label ='median')
x1 = student_data_math['G1'].describe()[4]
ax1.plot(x1+0.5, 60, 'blue', marker = 'o',markersize=10,label ='25percentile')
x1 = student_data_math['G1'].describe()[6]
ax1.plot(x1+0.5, 60, 'black', marker = 'o',markersize=10,label ='75percentile')
ax2.boxplot(y1)
ax2.set_xlabel('G1')
ax2.set_ylabel('count')
ax1.legend()
ax1.set_ylabel('count')
ax1.set_xlabel('G1')
plt.grid(True)
plt.show()

Figure_14-G1pp.png

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
y1 = [student_data_math['G1'],student_data_math['G2'],student_data_math['G3'],student_data_math['absences']]
ax1.boxplot(y1,labels=['G1', 'G2', 'G3', 'absences'])
ax1.set_xlabel('category')
ax1.set_ylabel('count')
ax1.legend()
ax1.set_ylabel('count')
ax1.set_xlabel('category')
plt.grid(True)
plt.show()

Figure_14-G1pp4.png
#####3-3-6 変動係数
変動係数CVとは、標準偏差σ/平均値$\bar{x}$
変動係数は、スケールに依存せず、散らばり具合が分かる。

print(student_data_math.std()/student_data_math.mean())
age           0.076427
Medu          0.398177
Fedu          0.431565
traveltime    0.481668
studytime     0.412313
failures      2.225319
famrel        0.227330
freetime      0.308725
goout         0.358098
Dalc          0.601441
Walc          0.562121
health        0.391147
absences      1.401873
G1            0.304266
G2            0.351086
G3            0.439881
dtype: float64

####3-3-7 散布図と相関係数

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
x = student_data_math['G1']
y = student_data_math['G3']
ax1.plot(x,y, 'o')
ax1.set_xlabel('G1-grade')
ax1.set_ylabel('G3-grade')
ax1.legend()
plt.grid(True)
plt.show()

G1-Gradeの高かった人は、G3-Gradeも高い。
ただし、G3-Gradeが0の人が数人出ている。これは、異常値だが、理由はいろいろちゅさして、除外するかどうか決めようという議論がされている。
Figure_15-G1G3.png
そこで、G3-Gradeが0の人の出席日数はどうなのということで、以下の相関図を描いて見る。

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
x = student_data_math['G3']
y = student_data_math['absences']
ax1.plot(x,y, 'o')
ax1.set_xlabel('G3-grade')
ax1.set_ylabel('absences')
ax1.legend()
plt.grid(True)
plt.show()

結果は、G3-Gradeが0の人は欠席0という結果。なんかおかしい。実は、途中でやめてノーカウントなのではとか想像できる。
Figure_15-G3absences.png
さらに、G1-Gradeと欠席数で相関取ると、以下の通り
Figure_15-G1absences.png
そもそも、G2-Gradeの時点で数名が0Gradeになっている。
Figure_15-G1G2.png
そして、G2-GradeとG3-Gradeの相関見ても、何人かは0Gradeに転落しており、そういう人も段々増えていることが分かる。そして、落伍者は点数の低めの人の中から出ているようだ。
だから、一つのグラフで結論を急ぐよりも、いろいろデータを分析することも大切だと言える。
Figure_15-G2G3.png
#####3-3-7-1 共分散
定義式は、以下の通り

S_{xy}=\frac{1}{n}\Sigma_{i=1}^{n}(x_i-\bar{x})(y_i-\bar{y})

すなわち、対角項は上で定義した分散になります。
では、非対角項は何を意味するのでしょう。
参考によれば、$x$と$y$が本来線形な関係があるとすると、最小二乗法で導かれる直線の方程式は以下となる。
【参考】
線形回帰分析・最小二乗法とは 共分散・相関係数の意味

y=\frac{S_{xy}}{\sigma^2_{x}}x + \bar y−\frac{S_{xy}}{\sigma^2_x}\bar x \\
変形すると、\\
\frac{y-\bar y}{\sigma_y}=\frac{S_{xy}}{\sigma_x\sigma_y}\frac{x-\bar x}{\sigma_x}

すなわち、標準偏差と平均値で規格化した一次方程式の傾きは以下の式となります。

r_{xy}=\frac{S_{xy}}{\sigma_x\sigma_y}

すなわち、共分散を標準偏差で規格化した値になり、これがいわゆる相関係数$r_{xy}$の定義式です。
#####3-3-7-2 相関係数
ここでは、共分散と相関係数を求めます。
共分散は、非対角項、対角項はG1,G3の分散です。

print(np.cov(student_data_math['G1'],student_data_math['G3']))
[[11.01705327 12.18768232]
 [12.18768232 20.9896164 ]]

相関係数は、前が相関係数、第二項はp値です。
※p値については後ろの章で取り上げる予定

print(sp.stats.pearsonr(student_data_math['G1'],student_data_math['G3']))
(0.801467932017414, 9.001430312277865e-90)

相関行列は、以下で求められます。

print(np.corrcoef(student_data_math['G1'],student_data_math['G3']))
[[1.         0.80146793]
 [0.80146793 1.        ]]

####3-3-8 すべての変数のヒストグラムや散布図を描く
Dalc;平日のアルコール摂取量
Walc;週末のアルコール摂取量
とG1,G3の得点に相関はあるか、散布図を描いて見る。
結果;無さそう

g = sns.pairplot(student_data_math[['Dalc','Walc','G1','G3']])
g.savefig('seaborn_pairplot_g.png')

seaborn_pairplot_g.png

【参考】
Python, pandas, seabornでペアプロット図(散布図行列)を作成
WalcとG3得点の相関無し

print(np.corrcoef(student_data_math['Walc'],student_data_math['G3']))
[[ 1.         -0.05193932]
 [-0.05193932  1.        ]]

グループ毎のバラツキ無し

print(student_data_math.groupby('Walc')['G3'].mean())
Walc
1    10.735099
2    10.082353
3    10.725000
4     9.686275
5    10.142857
Name: G3, dtype: float64

####練習問題3-1

              age        Medu        Fedu  traveltime  ...    absences          G1          G2          G3
count  649.000000  649.000000  649.000000  649.000000  ...  649.000000  649.000000  649.000000  649.000000
mean    16.744222    2.514638    2.306626    1.568567  ...    3.659476   11.399076   11.570108   11.906009
std      1.218138    1.134552    1.099931    0.748660  ...    4.640759    2.745265    2.913639    3.230656
min     15.000000    0.000000    0.000000    1.000000  ...    0.000000    0.000000    0.000000    0.000000
25%     16.000000    2.000000    1.000000    1.000000  ...    0.000000   10.000000   10.000000   10.000000
50%     17.000000    2.000000    2.000000    1.000000  ...    2.000000   11.000000   11.000000   12.000000
75%     18.000000    4.000000    3.000000    2.000000  ...    6.000000   13.000000   13.000000   14.000000
max     22.000000    4.000000    4.000000    4.000000  ...   32.000000   19.000000   19.000000   19.000000

####練習問題3-2

df =student_data_math.merge(student_data_por,left_on=['school','sex','age','address','famsize','Pstatus','Medu','Fedu','Mjob','Fjob','reason','nursery','internet'], right_on=['school','sex','age','address','famsize','Pstatus','Medu','Fedu','Mjob','Fjob','reason','nursery','internet'], suffixes=('_math', '_por'))
print(df.head())
  school sex  age address famsize Pstatus  ...  Walc_por  health_por absences_por G1_por G2_por G3_por
0     GP   F   18       U     GT3       A  ...         1           3            4      0     11     11
1     GP   F   17       U     GT3       T  ...         1           3            2      9     11     11
2     GP   F   15       U     LE3       T  ...         3           3            6     12     13     12
3     GP   F   15       U     GT3       T  ...         1           5            0     14     14     14
4     GP   F   16       U     GT3       T  ...         2           5            0     11     13     13

[5 rows x 53 columns]

####練習問題3-3

gm = sns.pairplot(df[['G1_math','G3_math','G1_por','G3_por']])
gm.savefig('seaborn_pairplot_gm.png')

mathどうし、porどうしの相関が高そう
mathよりporの方が分散は小さそう
seaborn_pairplot_gm.png
以下の結果からも裏付けられる。

print(np.corrcoef(df['G1_math'],df['G3_math']))
[[1.        0.8051287]
 [0.8051287 1.       ]]
print(np.corrcoef(df['G3_math'],df['G3_por']))
[[1.         0.48034936]
 [0.48034936 1.        ]]

print(np.cov(df['G1_math'],df['G3_math']))
[[11.2169202  12.63919693]
 [12.63919693 21.9702354 ]]
print(np.cov(df['G3_math'],df['G3_por']))
[[21.9702354   6.63169394]
 [ 6.63169394  8.67560567]]

###Chapter 3-4 単回帰分析
「記述統計の次は、回帰分析の基礎を学びましょう。」
「回帰分析とは、数値を予測する分析です。...上の学生のデータについて、グラフ化しました。この散布図から、G1とG3には関係がありそうだというのは分かります。」

fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
ax1.plot(student_data_math['G1'],student_data_math['G3'],'o')
ax1.set_xlabel('G1_Grade')
ax1.set_ylabel('G3_Grade')
ax1.grid(True)
plt.show()

Figure_16-G1G3.png
「回帰問題では、与えられたデータから関係式を仮定して、データに最も当てはまる係数を求めて行きます。具体的にはあらかじめわかっているG1の成績をもとに、G3の成績を予測します。つまり、目的となる変数G3(目的変数という)があり、それを説明する変数G1(説明変数という)を使って予測します。回帰分析では、説明変数が1つのものと、複数のものがあり、前者を単回帰、後者を重回帰分析と言います。この章では単回帰分析の説明をします。」
※若干意訳しています
####3-4-1 線形単回帰分析
「ここでは単回帰分析の内、アウトプットとインプットが線形の関係が成り立つことを前提とした線形単回帰という手法で回帰問題を解く方法を説明します。」

import pandas as pd
from sklearn import linear_model

reg = linear_model.LinearRegression()
student_data_math = pd.read_csv('./chap3/student-mat.csv', sep =';')

x = student_data_math.loc[:,['G1']].values
y = student_data_math['G3'].values
reg.fit(x,y)
print('回帰係数;',reg.coef_)
print('切片;',reg.intercept_)
回帰係数 [1.10625609]
切片 -1.6528038288004616
fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
ax1.plot(student_data_math['G1'],student_data_math['G3'],'o')
ax1.plot(x,reg.predict(x))
ax1.set_xlabel('G1_Grade')
ax1.set_ylabel('G3_Grade')
ax1.grid(True)
plt.show()

Figure_16-G1G3predict.png
####3-4-2 決定係数

R^2 = 1- \frac{\Sigma_{i=1}^{n}(y_i-f(x_i))^2}{\Sigma_{i=1}^{n}(y_i-\bar y)^2}

上式は、決定係数と呼ばれ、$R^2=1$が最大値であり、1に近ければ近いほど良いモデルになります。

print('決定係数;',reg.score(x,y))
決定係数 0.64235084605227

###総合問題3-2-1 Lorenz Curve

df0 = student_data_math[student_data_math['sex'].isin(['M'])]
df = df0.sort_values(by=['G1'])
df['Ct']=np.arange(1,len(df)+1)

x = df['Ct']
print(x)
y = df['G1'].cumsum()
print(y)
fig, (ax1) = plt.subplots(1, 1, figsize=(8,6))
ax1.plot(x/max(x),y/max(y))
ax1.set_xlabel('peoples')
ax1.set_ylabel('G1_Grade.cumsum')
ax1.grid(True)
plt.show()

248      1
144      2
164      3
161      4
153      5
      ...
113    183
129    184
245    185
42     186
47     187
Name: Ct, Length: 187, dtype: int32
248       3
144       8
164      13
161      18
153      23
       ...
113    2026
129    2044
245    2062
42     2081
47     2100
Name: G1, Length: 187, dtype: int64

Gini係数;(0,0)(1,1)を結んだ45度直線との間の面積の2倍;不平等の度合い
M
Figure_17-G1cumsumvspplesM.png
F
Figure_17-G1cumsumvspples.png
参考
M;G1 vs peaples
Figure_17-G1vspeoplesM.png
F;G1 vs peaples
Figure_17-G1vspeoples.png

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?