赤飯にかかったアレ

雑多なメモ帳

pythonで書くRによるやさしい統計学第2章

1つの変数の記述統計

書籍Rによるやさしい統計学pythonでも書きながら理解できたら
お得だと思いました。 全てではないですがやって見ようかなと思っています。

データとして、Rによるやさしい統計学を使用した大学の講義資料の中に
Rによるやさしい統計学に出てくるデータのcsvファイルを見つけたので使おうと思います。
社会統計演習

使用するデータ:指導法データの csv ファイル

  • データの説明
項目 意味
ID データ を 構成 する 人 たち の 通し番号
名前 各人の名前
数学 数学が好きですか?の問いに対する答えです。
回答は「好き」か「嫌い」のいずれか
統計 統計が好きですか?の問いに対する答えです。
回答は「好き」か「嫌い」のいずれか
心理学 試験科目のテスト得点です(20点満点)
統計テスト1 20人に、統計学の力が向上するような指導法を行う前に実施した統計学のテスト得点(20点満点)。
統計テスト2 20人に、統計学の力が向上するような指導法を行った後に実施した統計学のテスト得点
指導法 統計学の指導法4種類です。A、B、C、Dの4種類の指導 法が行われた

変数の種類

質的変数(qualitative variable)

データがカテゴリで示される。 データ間の「質」が違う変数

例 - 性別 - 名前

数値データではないので、そのままでは計算に利用することができない。
性別の質的変数の場合、選択肢は「男、女」二つになる(なる?)
このようなデータが二種類になるものを二値変数という

量的変数(quantitative variable)

データが数値で示される。 データの「量(数値)」が基準の変数

例 - 身長 - 体重 - 面積

数値データなので、そのまま計算にも利用することができる。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
data = pd.read_csv("./data/shidouhou.csv", encoding="SHIFT-JIS")
data
SID name sex math stat psych_test stat_test1 stat_test2 method
0 1 大村 嫌い 好き 13 6 10 C
1 2 本多 嫌い 好き 14 10 13 B
2 3 川崎 好き 好き 7 6 8 B
3 4 多村 好き 好き 12 10 15 A
4 5 松中 嫌い 嫌い 10 5 8 B
5 6 小久保 嫌い 嫌い 6 3 6 C
6 7 柴原 嫌い 嫌い 8 5 9 A
7 8 井手 嫌い 嫌い 15 9 10 D
8 9 田上 嫌い 嫌い 4 3 7 D
9 10 松田 好き 嫌い 14 3 3 D
10 11 高谷 好き 好き 9 11 18 A
11 12 杉内 嫌い 好き 6 6 14 A
12 13 和田 好き 好き 10 11 18 A
13 14 新垣 嫌い 嫌い 12 9 11 C
14 15 大隣 嫌い 好き 5 7 12 B
15 16 水田 好き 嫌い 12 5 5 D
16 17 斉藤 嫌い 嫌い 8 8 7 C
17 18 柳瀬 嫌い 嫌い 8 7 12 C
18 19 佐藤 嫌い 嫌い 12 7 7 B
19 20 馬原 嫌い 嫌い 15 9 7 D
data.dtypes
SID            int64
name          object
sex           object
math          object
stat          object
psych_test     int64
stat_test1     int64
stat_test2     int64
method        object
dtype: object
# 数値変換
for col in ["psych_test", "psych_test", "stat_test1", "stat_test2"]:
    data[col] = pd.to_numeric(data[col], errors="coerce")
data.dtypes
SID            int64
name          object
sex           object
math          object
stat          object
psych_test     int64
stat_test1     int64
stat_test2     int64
method        object
dtype: object
data.head()
SID name sex math stat psych_test stat_test1 stat_test2 method
0 1 大村 嫌い 好き 13 6 10 C
1 2 本多 嫌い 好き 14 10 13 B
2 3 川崎 好き 好き 7 6 8 B
3 4 多村 好き 好き 12 10 15 A
4 5 松中 嫌い 嫌い 10 5 8 B
data.tail()
SID name sex math stat psych_test stat_test1 stat_test2 method
15 16 水田 好き 嫌い 12 5 5 D
16 17 斉藤 嫌い 嫌い 8 8 7 C
17 18 柳瀬 嫌い 嫌い 8 7 12 C
18 19 佐藤 嫌い 嫌い 12 7 7 B
19 20 馬原 嫌い 嫌い 15 9 7 D
data['math']
0     嫌い
1     嫌い
2     好き
3     好き
4     嫌い
5     嫌い
6     嫌い
7     嫌い
8     嫌い
9     好き
10    好き
11    嫌い
12    好き
13    嫌い
14    嫌い
15    好き
16    嫌い
17    嫌い
18    嫌い
19    嫌い
Name: math, dtype: object

度数分布

  • 度数
    同じカテゴリに含まれるデータの個数

  • 度数分布
    すべてのカテゴリの度数をまとめたもの

  • 度数分布表
    度数分布を表にしたもの

# 指導法のデータを取得
teach = data["method"]
teach
0     C
1     B
2     B
3     A
4     B
5     C
6     A
7     D
8     D
9     D
10    A
11    A
12    A
13    C
14    B
15    D
16    C
17    C
18    B
19    D
Name: method, dtype: object
# 度数分布
print("A:{0}".format(teach[teach == "A"].count()))
print("B:{0}".format(teach[teach == "B"].count()))
print("C:{0}".format(teach[teach == "C"].count()))
print("D:{0}".format(teach[teach == "D"].count()))
A:5
B:5
C:5
D:5
print(pd.get_dummies(teach))
    A  B  C  D
0   0  0  1  0
1   0  1  0  0
2   0  1  0  0
3   1  0  0  0
4   0  1  0  0
5   0  0  1  0
6   1  0  0  0
7   0  0  0  1
8   0  0  0  1
9   0  0  0  1
10  1  0  0  0
11  1  0  0  0
12  1  0  0  0
13  0  0  1  0
14  0  1  0  0
15  0  0  0  1
16  0  0  1  0
17  0  0  1  0
18  0  1  0  0
19  0  0  0  1
x = np.array(["A", "B", "C", "D"])
y = np.array([teach[teach == "A"].count(), teach[teach == "B"].count(), 
             teach[teach == "C"].count(), teach[teach == "D"].count()])
plt.bar(x, y)
plt.xlabel("$method$")
plt.ylabel("$frequency$")
plt.title("$frequency distribution$")
plt.grid()

f:id:sekihan_0290:20200126192552p:plain

度数分布を視覚的にわかりやすく示すために階級という区切りを作り棒グラフで図示する

# 心理学テスト結果をヒストグラムで表す
psych_test = data["psych_test"]

frequency = np.histogram(psych_test, bins=10, range = (0, 20))
frequency
(array([0, 0, 2, 3, 4, 2, 5, 4, 0, 0], dtype=int64),
 array([ 0.,  2.,  4.,  6.,  8., 10., 12., 14., 16., 18., 20.]))
frequency,_ = np.histogram(psych_test, bins=10, range = (0, 20))
frequency
array([0, 0, 2, 3, 4, 2, 5, 4, 0, 0], dtype=int64)
plt.hist(psych_test, bins=10, range=(0, 20))
plt.xlim(0, 20)
plt.ylim(0, 8)
plt.xlabel("$psych_test$")
plt.ylabel("$frequency$")
plt.title("$histogram$")
plt.grid()

f:id:sekihan_0290:20200126192705p:plain

平均

データを全て足し、データ数で割る。 $$\overline{x} = \frac{1}{n} \sum_{i=1}^n{x_i}$$

psych_test = data["psych_test"]
np.mean(psych_test)
10.0
sum(psych_test)/len(psych_test)
10.0
# 欠損値有のデータで平均起算
x = np.array([1, 4, np.nan, 1])
x
array([ 1.,  4., nan,  1.])
np.mean(x)
nan
# 欠損値の確認
pd.isnull(x)
array([False, False,  True, False])
# x配列内のpd.isnull()の結果がFalseを表示
x[~pd.isnull(x)]
array([1., 4., 1.])
np.mean(x[~pd.isnull(x)])
2.0
# 欠損値数の集計
sum(pd.isnull(x))
1
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 9 columns):
SID           20 non-null int64
name          20 non-null object
sex           20 non-null object
math          20 non-null object
stat          20 non-null object
psych_test    20 non-null int64
stat_test1    20 non-null int64
stat_test2    20 non-null int64
method        20 non-null object
dtypes: int64(4), object(5)
memory usage: 1.5+ KB
data.isnull().any(axis=0)
SID           False
name          False
sex           False
math          False
stat          False
psych_test    False
stat_test1    False
stat_test2    False
method        False
dtype: bool
# isnull().sum()を使用して欠損値を集計
data.isnull().sum()
SID           0
name          0
sex           0
math          0
stat          0
psych_test    0
stat_test1    0
stat_test2    0
method        0
dtype: int64

平均以外の代表値

  • 代表値
    データの分布状況をとらえるための統計量の総称
    データの中心

中央値

データの大きさの順に並べたときの真ん中の位置する値
偶数のときはちょうど真ん中の値が無いので、真ん中の$2$つの値の平均を中央値とする

最瀕値

最も多く出現したデータ

# 中央値
np.median(psych_test)
10.0
# 中央値の確認
print("データ数:{}" .format(psych_test.count()))
print("中央値:{}" .format((np.sort(psych_test)[9] + np.sort(psych_test)[10])/2))
データ数:20
中央値:10.0
pd.Series(psych_test)
0     13
1     14
2      7
3     12
4     10
5      6
6      8
7     15
8      4
9     14
10     9
11     6
12    10
13    12
14     5
15    12
16     8
17     8
18    12
19    15
Name: psych_test, dtype: int64
# 最瀕値
pd.Series(psych_test).mode()
0    12
dtype: int64

分散、 標準偏差 とは

データを要約するとき、代表値のほかに散布度を使う

  • 散布度
    データの散らばり具合

分散

平均値からそれぞれのデータがどれだけ離れているかをあらわしたもの $$ s2 = \frac{1}{n} \sum_{i=1}^n({x_i-\overline{x} })2$$ 計算上、2乗の平均値引く平均の2乗で求められる。

標準偏差

$$ s = \sqrt{\frac{1}{n} \sum_{i=1}^n({x_i-\overline{x} })2}$$

# 分散
print(np.var(psych_test))
print( sum((psych_test - np.mean(psych_test))**2)/len(psych_test) )
print(np.mean((psych_test - np.mean(psych_test))**2))
11.1
11.1
11.1
# 標準偏差
print(np.std(psych_test))
print(np.sqrt(np.mean((psych_test - np.mean(psych_test))**2)))
3.331666249791536
3.331666249791536

標準化

標準偏差を他のデータと一緒に使えるように共通化したもの変換された得点を標準得点といい、
平均$0$、標準偏差$1$になるような変換をz得点という $$z = \frac{x-\overline x}{s}$$

# 標準化
x = psych_test
m = np.mean(psych_test)
s = np.std(psych_test)

z = (x - m) / s
z
0     0.900450
1     1.200600
2    -0.900450
3     0.600300
4     0.000000
5    -1.200600
6    -0.600300
7     1.500751
8    -1.800901
9     1.200600
10   -0.300150
11   -1.200600
12    0.000000
13    0.600300
14   -1.500751
15    0.600300
16   -0.600300
17   -0.600300
18    0.600300
19    1.500751
Name: psych_test, dtype: float64

偏差値

平均を$50$、標準偏差を$10$になるような値 z得点を$10$倍して$50$を足したもの $$偏差値 = z × 10 + 50 $$

# 標準化
x = psych_test
m = np.mean(psych_test)
s = np.sqrt(np.mean( (psych_test - m)**2 ) )
z = (x - m)/s
# 標準偏差
a = z*10 + 50
a
0     59.004503
1     62.006005
2     40.995497
3     56.003002
4     50.000000
5     37.993995
6     43.996998
7     65.007506
8     31.990993
9     62.006005
10    46.998499
11    37.993995
12    50.000000
13    56.003002
14    34.992494
15    56.003002
16    43.996998
17    43.996998
18    56.003002
19    65.007506
Name: psych_test, dtype: float64

練習問題

  1. 以下 は A 大学 と B 大学 の 学生( 各 10 人) の 一日 の テレビ 視聴 時間( 単位 は 分) の データ です。 大学 ごと に ヒストグラム を 描い て み ましょ う。
    A 大学: 60, 100, 50, 40, 50, 230, 120, 240, 200, 30
    B 大学: 50, 60, 40, 50, 100, 80, 30, 20, 100, 120

  2. 上記 データ について、 大学 ごと に 平均 と 標準偏差 を 求め て み ましょ う。

  3. 上記 データ について、 大学 ごと に データ を 標準化 し て み ましょ う。

# (1)
A = np.array([60, 100, 50, 40, 50, 230, 120, 240, 200, 30])
B = np.array([50, 60, 40, 50, 100, 80, 30, 20, 100, 120])

# 250 50ずつ
plt.hist([A, B], bins=10, range=(0, 250), label=["$A$", "$B$"])
# plt.hist(B, bins=5, range=(0, 250), label="B")
plt.legend()
plt.xlabel("$minutes$")
plt.ylabel("$member$")
plt.title("$histogram$")
plt.grid()

f:id:sekihan_0290:20200126192744p:plain

# (2)
print("A大学の平均{} 標準偏差{}".format(np.mean(A), np.std(A)))
print("B大学の平均{} 標準偏差{}".format(np.mean(B), np.std(B)))
A大学の平均112.0 標準偏差77.82030583337487
B大学の平均65.0 標準偏差31.701734968294716
# (3)
print("A大学の標準化\n{}".format( (A - np.mean(A)) / np.std(A)))
print("B大学の標準化\n{}".format( (B - np.mean(B)) / np.std(B)))
A大学の標準化
[-0.66820606 -0.1542014  -0.79670723 -0.92520839 -0.79670723  1.51631375
  0.10280093  1.64481492  1.13081026 -1.05370956]
B大学の標準化
[-0.47316022 -0.15772007 -0.78860037 -0.47316022  1.10404052  0.47316022
 -1.10404052 -1.41948067  1.10404052  1.73492082]

Pythonで書く、へっぽこ社会人の統計学習[度数分布]

度数分布

DoDStat@d データ指向統計データベース データセット一覧の分布の型を使用し、異なる分布に従う4つの変量から 度数分布を求める

平均値や分散度の2つの測度だけでもデータの全体的特徴を把握する事はできるが、もっと詳しくデータの分布状況を見るために用いられるものが、度数分布、または類度分布を用いる。

度数分布(frequency distribution)は、データを特定の区間で区切り、その区間に入るデータの数を明らかにしたもの。

  • 階級(class) : 区切られたデータの区間
  • 度数(frequency) : 階級に入るデータ数

度数が色々な階級にどのように別れて広がっているかを表す。

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
%matplotlib inline
data = pd.read_csv("data/distribu.csv")
data.head()
QRAT STR AGE DENS
0 114.0 66 47.0 550.0
1 79.0 117 47.0 561.0
2 76.0 132 48.0 488.0
3 109.0 111 48.0 507.0
4 117.0 107 48.0 526.0
data = data.rename(columns={"QRAT": "250の中から選択された50の企業の市場価値と取替原価の比率", 
                            "DENS": "1798年にキャベンディッシュによる陸地の比重 (Stigler より)", 
                            "STR": "22本の紬糸から選択した1本の糸の長さ (lbs) (A.J. Duncan より)", 
                            "AGE":"オランダ空軍の大佐の年齢 (Verhoeven より)"})
data.head()
250の中から選択された50の企業の市場価値と取替原価の比率 22本の紬糸から選択した1本の糸の長さ (lbs) (A.J. Duncan より) オランダ空軍の大佐の年齢 (Verhoeven より) 1798年にキャベンディッシュによる陸地の比重 (Stigler より)
0 114.0 66 47.0 550.0
1 79.0 117 47.0 561.0
2 76.0 132 48.0 488.0
3 109.0 111 48.0 507.0
4 117.0 107 48.0 526.0
data.dtypes
250の中から選択された50の企業の市場価値と取替原価の比率                float64
22本の紬糸から選択した1本の糸の長さ (lbs) (A.J. Duncan より)      int64
オランダ空軍の大佐の年齢 (Verhoeven より)                   float64
1798年にキャベンディッシュによる陸地の比重 (Stigler より)          float64
dtype: object
data.shape
(100, 4)
# 度数分布
age = data["オランダ空軍の大佐の年齢 (Verhoeven より)"]
frequency = np.histogram(age, bins=10, range=(0, 100))
frequency
(array([ 0,  0,  0,  0, 12, 77,  0,  0,  0,  0]),
 array([  0.,  10.,  20.,  30.,  40.,  50.,  60.,  70.,  80.,  90., 100.]))
frequency, _ = np.histogram(age, bins=10, range=(0, 100))
frequency
array([ 0,  0,  0,  0, 12, 77,  0,  0,  0,  0])
# DataFrame
freq_class = [f"{i}〜{i+10}" for i in range(0, 100, 10)]

frequency_df = pd.DataFrame({"度数" : frequency},
                           index = pd.Index(freq_class,
                                           name="階級"))
frequency_df
度数
階級
0〜10 0
10〜20 0
20〜30 0
30〜40 0
40〜50 12
50〜60 77
60〜70 0
70〜80 0
80〜90 0
90〜100 0
np.min(age)
47.0

相対度数分布

度数分布は各階級に属する度数を示す。 分布の状態を各階級の度数を全度数で割った相対度数で表示するとわかりやすい、この表を相対度分布という

  • 相対度数 : 全データに対する対象の階級のデータの割合
rel = frequency / frequency.sum()
rel
array([0.        , 0.        , 0.        , 0.        , 0.13483146,
       0.86516854, 0.        , 0.        , 0.        , 0.        ])
frequency_df["相対度数"] = rel
frequency_df
度数 相対度数
階級
0〜10 0 0.000000
10〜20 0 0.000000
20〜30 0 0.000000
30〜40 0 0.000000
40〜50 12 0.134831
50〜60 77 0.865169
60〜70 0 0.000000
70〜80 0 0.000000
80〜90 0 0.000000
90〜100 0 0.000000

累積度数分布

試験の成績が50点以下の人数や、80点以上の人数というように 度数の中で、ある値以上と以下の度数に注目する場合がある

この時、ある階級以下の度数を下からの累積度数、ある階級以上の度数を上からの累積度数といい、ある階級までの相対度数の和を累積相対度数という。

cum_rel = np.cumsum(rel)
cum_rel
array([0.        , 0.        , 0.        , 0.        , 0.13483146,
       1.        , 1.        , 1.        , 1.        , 1.        ])
frequency_df["累積度数"] = cum_rel
frequency_df
度数 相対度数 累積度数
階級
0〜10 0 0.000000 0.000000
10〜20 0 0.000000 0.000000
20〜30 0 0.000000 0.000000
30〜40 0 0.000000 0.000000
40〜50 12 0.134831 0.134831
50〜60 77 0.865169 1.000000
60〜70 0 0.000000 1.000000
70〜80 0 0.000000 1.000000
80〜90 0 0.000000 1.000000
90〜100 0 0.000000 1.000000

度数分布のグラフ

ヒストグラム

度数分布を視覚的にわかりやすく示すために 横軸に変数の値、縦軸に度数をとり、グラフ化したヒストグラム(histogram)でグラフ化し、可視化する。

ヒストグラムの他にヒストグラムの柱の頂点の中心を結んでできる折れ線グラフで度数分布を図示することもでき、これを度数折れ線という

plt.grid()
plt.hist(age, bins=10, range=(0, 100))
(array([ 0.,  0.,  0.,  0., 12., 77.,  0.,  0.,  0.,  0.]),
 array([  0.,  10.,  20.,  30.,  40.,  50.,  60.,  70.,  80.,  90., 100.]),
 <a list of 10 Patch objects>)

[f:id:sekihan_0290:20200117222146p:plain]

plt.grid()
plt.hist(age, bins=20, range=(0, 100))
(array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0., 12., 77.,  0.,  0.,
         0.,  0.,  0.,  0.,  0.,  0.,  0.]),
 array([  0.,   5.,  10.,  15.,  20.,  25.,  30.,  35.,  40.,  45.,  50.,
         55.,  60.,  65.,  70.,  75.,  80.,  85.,  90.,  95., 100.]),
 <a list of 20 Patch objects>)

f:id:sekihan_0290:20200117222143p:plain

Pythonで書く、へっぽこ社会人の統計学習[平均と分散]

 

 

 

 

何故必要になったのか

2020年1月から転職をした結果、データを使った占い師になってしまい逃げ続けていた統計をとうとう使うことになってしまいました。

こうなったら一緒に使うpythonも使いながら統計を使いつつ備忘録を残そうと思います。

※ jupyter notebookって色々な形式に変換できるんですね

 

平均値と分散

e-stat 男女別人口-全国,都道府県(大正9年~平成27年)の国勢調査データから 平均と分散を求めるところから始めたいと思います

In [1]:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
%matplotlib inline
# 有効桁数を3桁にする
pd.set_option("precision", 3)
In [2]:
# データの読み込み
data = pd.read_csv("data/Census.csv", encoding="shift-jis")
In [3]:
data.head()
Out[3]:
 
  都道府県コード 都道府県名 元号 和暦(年) 西暦(年) 人口(総数) 人口(男) 人口(女)
0 00 全国 大正 9.0 1920.0 NaN 55963053 28044185 27918868
1 01 北海道 大正 9.0 1920.0 NaN 2359183 1244322 1114861
2 02 青森県 大正 9.0 1920.0 NaN 756454 381293 375161
3 03 岩手県 大正 9.0 1920.0 NaN 845540 421069 424471
4 04 宮城県 大正 9.0 1920.0 NaN 961768 485309 476459
In [4]:
data.dtypes
Out[4]:
都道府県コード     object
都道府県名       object
元号          object
和暦(年)      float64
西暦(年)      float64
注           object
人口(総数)      object
人口(男)       object
人口(女)       object
dtype: object
In [5]:
# カラム名の変更
df = data.rename(columns={"人口(総数)": "全人口", "人口(男)": "男", "人口(女)": "女"})
df.head()
Out[5]:
 
  都道府県コード 都道府県名 元号 和暦(年) 西暦(年) 全人口
0 00 全国 大正 9.0 1920.0 NaN 55963053 28044185 27918868
1 01 北海道 大正 9.0 1920.0 NaN 2359183 1244322 1114861
2 02 青森県 大正 9.0 1920.0 NaN 756454 381293 375161
3 03 岩手県 大正 9.0 1920.0 NaN 845540 421069 424471
4 04 宮城県 大正 9.0 1920.0 NaN 961768 485309 476459
In [6]:
# objectをfloatに変換
for i in ["都道府県コード", "全人口", "男", "女"]:
    df[i] = pd.to_numeric(df[i], errors="coerce")
In [7]:
df.dtypes
Out[7]:
都道府県コード    float64
都道府県名       object
元号          object
和暦(年)      float64
西暦(年)      float64
注           object
全人口        float64
男          float64
女          float64
dtype: object
In [8]:
# 人口の抽出
populations = np.array(df["全人口"])[1:11]
populations
Out[8]:
array([2359183.,  756454.,  845540.,  961768.,  898537.,  968925.,
       1362750., 1350400., 1046479., 1052610.])
In [9]:
df["全人口"].head(12)
Out[9]:
0     5.596e+07
1     2.359e+06
2     7.565e+05
3     8.455e+05
4     9.618e+05
5     8.985e+05
6     9.689e+05
7     1.363e+06
8     1.350e+06
9     1.046e+06
10    1.053e+06
11    1.320e+06
Name: 全人口, dtype: float64
In [10]:
# 都道府県名の抽出(最初の全国は除いて抜き出す)
prefectures = df["都道府県名"][1:11]
prefectures
Out[10]:
1     北海道
2     青森県
3     岩手県
4     宮城県
5     秋田県
6     山形県
7     福島県
8     茨城県
9     栃木県
10    群馬県
Name: 都道府県名, dtype: object
In [11]:
# 結合
data=pd.DataFrame({"人口":populations},
                 index=pd.Index(prefectures,
                               name="都道府県名"))
data
Out[11]:
 
  人口
都道府県名  
北海道 2.359e+06
青森県 7.565e+05
岩手県 8.455e+05
宮城県 9.618e+05
秋田県 8.985e+05
山形県 9.689e+05
福島県 1.363e+06
茨城県 1.350e+06
栃木県 1.046e+06
群馬県 1.053e+06
 

平均値

データを全て足し、データ数で割る。 $$\overline{x} = \frac{1}{n} \sum_{i=1}^n{x_i}$$

In [12]:
# 平均値
sum(data["人口"])/len(data["人口"])
Out[12]:
1160264.6
In [13]:
# numpyで平均
np.mean(data)
Out[13]:
人口    1.160e+06
dtype: float64
In [14]:
data.mean()
Out[14]:
人口    1.160e+06
dtype: float64
 

中央値

データを大きさの順に並べたときにちょうど中央に位置するデータを中央値(median)といい、

データ数$n$が偶数の時はデータ数の真ん中に当たる値が二つでき、 それを足して$2$で割ったもの$\frac{n}{2}$と$\frac{n+1}{2}$の平均を中央値として求める

データ数$n$が奇数の時は$\frac{(n+1)}{2}$で求める

In [15]:
# 中央値
np.median(data)
Out[15]:
1007702.0
In [16]:
data.median()
Out[16]:
人口    1.008e+06
dtype: float64
In [17]:
sort_populat = np.sort(np.array([1, 1, 2, 2, 3, 3, 4]))
# sort_populat = np.sort(data["人口"])
n_len = len(sort_populat)

if (n_len % 2) == 0:
    m0 = sort_populat[n_len//2-1]
    m1 = sort_populat[n_len//2]
    median = (m0 + m1)/2
else:
    median = sort_populat[(n_len+1)//2 -1]

median
Out[17]:
2
 

最頻値(mode)

データの中でもっとも多く出現するデータを最頻値という

In [18]:
pd.Series([1,1,1,2,2,3]).mode()
Out[18]:
0    1
dtype: int64
 

分散と標準偏差

平均値や中央値はそのデータ全体の性質を判断するために用いられ、 代表値とも呼ばれる。

この代表値と各データを比較した時のバラツキの尺度を比較することで、

データの特殊性が判断できる。

偏差(deviation)

偏差は各データが平均からどれだけ離れているかを示し、 その平均的な大きさで数値の分散度を測定できる。

各データを平均値で引くことで求める $$ \sum_{i=1}^n{x_i-\overline{x} }$$

また偏差の平均は0になる。

In [19]:
mean = np.mean(data["人口"])
deviation = data["人口"] - mean
deviation
Out[19]:
都道府県名
北海道    1.199e+06
青森県   -4.038e+05
岩手県   -3.147e+05
宮城県   -1.985e+05
秋田県   -2.617e+05
山形県   -1.913e+05
福島県    2.025e+05
茨城県    1.901e+05
栃木県   -1.138e+05
群馬県   -1.077e+05
Name: 人口, dtype: float64
In [20]:
np.mean(deviation)
Out[20]:
-9.313225746154786e-11
In [21]:
mean = np.mean(populations)
deviation = populations - mean
print(deviation)
print(np.mean(deviation))
 
[1198918.4 -403810.6 -314724.6 -198496.6 -261727.6 -191339.6  202485.4
  190135.4 -113785.6 -107654.6]
-9.313225746154786e-11
In [22]:
# Dataframeに偏差を追加
summary_df = data.copy()
summary_df["偏差"] = deviation
summary_df
Out[22]:
 
  人口 偏差
都道府県名    
北海道 2.359e+06 1.199e+06
青森県 7.565e+05 -4.038e+05
岩手県 8.455e+05 -3.147e+05
宮城県 9.618e+05 -1.985e+05
秋田県 8.985e+05 -2.617e+05
山形県 9.689e+05 -1.913e+05
福島県 1.363e+06 2.025e+05
茨城県 1.350e+06 1.901e+05
栃木県 1.046e+06 -1.138e+05
群馬県 1.053e+06 -1.077e+05
 

標準偏差と分散

平均とのデータの散らばりの尺度は、偏差の平均の大きさで測定できる。

偏差の平均は0だが、偏差の大きさがわかればよく、正負は考えなくて良い。

絶対値を使う方法もあるが、便利ではなく2乗値を用いた 標準偏差を用いる。

標準偏差(s)は以下のように表し、偏差の大きさの平均を表す。 $$ s = \sqrt{\frac{1}{n} \sum_{i=1}^n({x_i-\overline{x} })^2}$$

また、計算上$s^2$を使用することもあり、 $s^2$を分散という 分散の定義は平均値からの偏差の2乗の平均だが、 計算上、2乗の平均値引く平均の2乗で求められる。

In [23]:
# 標準偏差
print(np.sqrt(np.var(data["人口"])))
print(np.std(data["人口"]))
 
441103.32881677506
441103.32881677506
In [24]:
# 分散
print(np.mean(summary_df["偏差"]**2))
print(np.var(data["人口"]))
 
194572146693.24
194572146693.24
 

範囲と四分位偏差

標準偏差以外の分散度の表し方としてデータの最大値と最小値の差を比較してその範囲から分散度を確認する方法があり、 これを範囲(range)という $$R = x_{max} - x_{min}$$

最大値と最小値だけで分散度を確認する方法は、 最大最小が中間のデータとかけ離れている時、 この値は分散度として必ずしも適切ではない。

そこで、極端なデータの影響を受けない測度として、 四分位数(quartile)を利用した四分位偏差(quartile deviation)という。

四分位数は全体のデータを小さい方から大きい方へ並べた時、 データ数を4等分する位置の値で、 データの下位25%、50%、75%に位置する値を第1四分位数、第2四分位数、第3四分位数と呼び、 $Q_1, Q_2, Q_3$で表す。

四分位偏差は$QD$と書ける $$QD = \frac{Q_3-Q_1}{2}$$

In [25]:
# 範囲(Range)
np.max(data["人口"])-np.min(data["人口"])
Out[25]:
1602729.0
In [26]:
# 四分位偏差
pre_Q1 = np.percentile(data["人口"], 25)
pre_Q3 = np.percentile(data["人口"], 75)

QD = (pre_Q3 - pre_Q1) / 2
QD
Out[26]:
180803.875
 

箱ひげ図(box plot)

四分位数を図示するときには箱ひげ図を使用し図示する。

平均値ではなく中央値を用いることで、 データの真ん中を表現でき、複数のデータ(母集団)を同時に扱える。

中央値を箱の中の横線として引く。

四分位数のうち、箱の上辺を第1四分位数、 箱の底辺を第3四分位数として線を引き箱を完成させる。

第1四分位数と第3四分位数の長さの1.5倍の範囲を把握し、 その範囲より外側にある数値を外れ値として点を記入する。

In [27]:
plt.boxplot(data["人口"], labels=["population"])
Out[27]:
{'whiskers': [<matplotlib.lines.Line2D at 0x10f5c5828>,
  <matplotlib.lines.Line2D at 0x10f5c5cc0>],
 'caps': [<matplotlib.lines.Line2D at 0x10f5d7128>,
  <matplotlib.lines.Line2D at 0x10f5d7550>],
 'boxes': [<matplotlib.lines.Line2D at 0x10f5c56d8>],
 'medians': [<matplotlib.lines.Line2D at 0x10f5d7978>],
 'fliers': [<matplotlib.lines.Line2D at 0x10f5d7da0>],
 'means': []}
 
In [28]:
# データの指標のまとめ
pd.Series(data["人口"]).describe()
Out[28]:
count    1.000e+01
mean     1.160e+06
std      4.650e+05
min      7.565e+05
25%      9.143e+05
50%      1.008e+06
75%      1.276e+06
max      2.359e+06
Name: 人口, dtype: float64
In [29]:
data["人口"].describe()
Out[29]:
count    1.000e+01
mean     1.160e+06
std      4.650e+05
min      7.565e+05
25%      9.143e+05
50%      1.008e+06
75%      1.276e+06
max      2.359e+06
Name: 人口, dtype: float64
 

正規化(normalization)

標準偏差は平均から求めることができるが、この指標は平均が異なるようなデータ間では比較することができない。 これを統一的な指標に変換することを正規化という

標準化(standardization)と標準化変量(standardized data)

正規化のうち、特にデータを平均から標準偏差の何倍離れているかという値で表し、そのデータの分布上の相対的な位置の比較を可能にする事を標準化という $$z = \frac{x - \overline{x}}{s}$$

データxをzに変換する事で異なるクラス間で比較可能になる。 この標準化されたzを標準化変量、またはzスコアという

In [30]:
z = (data["人口"] - np.mean(data["人口"])) / np.std(data["人口"])
z
Out[30]:
都道府県名
北海道    2.718
青森県   -0.915
岩手県   -0.713
宮城県   -0.450
秋田県   -0.593
山形県   -0.434
福島県    0.459
茨城県    0.431
栃木県   -0.258
群馬県   -0.244
Name: 人口, dtype: float64
 

偏差値

標準偏差10、平均が50になるように正規化した値を偏差値という $$z_i = 50+10 \times \frac{x_i - \overline{x}}{S}$$

In [31]:
# 偏差値
z = 50 + 10 * (data["人口"] - np.mean(data["人口"])) / np.std(data["人口"])
z
Out[31]:
都道府県名
北海道    77.180
青森県    40.845
岩手県    42.865
宮城県    45.500
秋田県    44.067
山形県    45.662
福島県    54.590
茨城県    54.310
栃木県    47.420
群馬県    47.559
Name: 人口, dtype: float64

Arduino統合開発環境「MariaMole」のインストール

Arduino統合開発環境に「MariaMole」というものがあるらしい

デフォルトのIDEは複数のプロジェクト管理がちょっと…(-_-;)

なので使ってみようと思います。

※MariaMole

f:id:sekihan_0290:20181006090909p:plain

 

続きを読む

太宰治の文章からボットを作る

 マルコフ連鎖の練習も兼ねて
マルコフ連鎖を使用した対話モデルを作って遊んでます。

(マルコフ連鎖とその学習のやり方は、ほぼ以下の書籍の写経です)

マルコフ連鎖とは

 マルコフ連鎖は確率過程の一つと考えていいのかな

  • 別名マルコフ過程
  • 確率過程を使って文章をつなぎ合わせて文を作る
  • マルコフ性(次に予測される状態が過去の状態に依存せず、現在の状態によってのみ決まる性質)を持つ確率過程のうち取り売る値が離散的なもの(マルコフ性を備えた確率過程を総称したマルコフ過程の中でも取る可能性のある値が連続的でなく離散的)これを特にマルコフ連鎖という・・・らしいよ

文の類似度を調べるN-gramの基本原理ってことでいいかな

 

次に来る文字を予測するLSTMでも試したけど、こっちの方が意味が通じる
パラメータ調整をミスってるのもあると思うけど、学習に時間かかりすぎるので却下

続きを読む

AIに文章を書かせたい! [Keras-LSTMサンプルコードで太宰治に文章を書かせたい]

機械の文章力の成長過程が見たい!!

テキストマイニングがしたい! part3. ディープラーニング幼稚園児の文章生成編 [Keras-LSTM文字生成サンプルコード] - 赤飯にかかったアレ

の続きです。

前は

  • 使ったテキストが少なかった(短編1作品のみ)
  • 形態素解析してない文章を使っていた
  • 理解度0でサンプルコード実行しただけ(今回もだけど...)

太宰治の文章をMeCab分かち書きし、KerasのLSTMサンプルコードにちょっと手を加えて文章を生成します。

ついでにWord2Vecでモデルも作ってみます。

 

機械の文章力の成長過程が見たい!!

ジュババァって機械動くの気持ちいいよね

 

あっ!ついでだけど芥川龍之介でこれやったら芥川賞クラスの文になるのかな? 試せたら試そう。

# 念のため_______________

AIという言葉は、色々な解釈ができると思います。

僕のAIの定義は学習し、判断できるものです。

今回は、

  • 事前に文章から辞書を作る。
  • テキストをベクトル化する、モデルを作る。
  • 学習して文章を生成する。

ということを行います。

学習と判断を行うため、タイトルにAIを入れました。

これをみっちゃった人のAIの定義と違ってたらごめんね

 _________________

続きを読む