Jupyterで統計のお勉強_データの散らばりを見る

  • このエントリーをはてなブックマークに追加
  • LINEで送る

工場の製造ラインで同じものを作っていても、作られたものはそれぞれ微妙な誤差ができてしまうものだし、人間の身長だってたくさんデータを集めればそれだけいろいろな数値が集まるはず。 

そんなデータから、何かしら情報や特徴を捉えるのが統計。 

とくに平均値というものはいたるところで使われるが、大きすぎたり小さすぎたりする値が混ざると、平均値がそれに引っ張られてしまいます。 

平均年収とかでよく問題?になるやつ。(そんなにもらってねーよ的な) 

平均は平均でしかなく、中にどんなデータがあるかまではわからないので、 平均に対してどれくらい散らばりがあるかを見ていきます。 

よくあるアヤメのデータセットでは面白みがないので、オープンデータを使用します。 

オープンデータを扱えるサイトの、 

https://www.data.go.jp/ 

気象観測_最新の気象データから最高気温のデータを取得しました。 

使用したサンプルデータです(xlsxファイルをダウンロード)

実行環境 

Jupyter Notebook  

  • pandas 0.24.2  
  • numpy 1.16.4 
  • xlrd 1.2.0 
In [1]:
import pandas as pd
In [2]:
df = pd.read_excel('全国の最高気温.xlsx')
In [3]:
#どんな項目があるのかを確認します。
df.columns
Out[3]:
Index(['観測所番号', '都道府県', '地点', '国際地点番号', '現在時刻(年)', '現在時刻(月)', '現在時刻(日)',
       '現在時刻(時)', '現在時刻(分)', '今日の最高気温(℃)', '今日の最高気温の品質情報', '今日の最高気温起時(時)',
       '今日の最高気温起時(分)', '今日の最高気温起時の品質情報', '平年差(℃)', '前日差(℃)', '該当旬(月)',
       '該当旬(旬)', '極値更新', '10年未満での極値更新', '今年最高', '今年の最高気温(℃)(昨日まで)',
       '今年の最高気温(昨日まで)の品質情報', '今年の最高気温(昨日まで)を観測した起日(年)',
       '今年の最高気温(昨日まで)を観測した起日(月)', '今年の最高気温(昨日まで)を観測した起日(日)',
       '昨日までの観測史上1位の値(℃)', '昨日までの観測史上1位の値の品質情報', '昨日までの観測史上1位の値を観測した起日(年)',
       '昨日までの観測史上1位の値を観測した起日(月)', '昨日までの観測史上1位の値を観測した起日(日)', '昨日までの7月の1位の値',
       '昨日までの7月の1位の値の品質情報', '昨日までの7月の1位の値の起日(年)', '昨日までの7月の1位の値の起日(月)',
       '昨日までの7月の1位の値の起日(日)', '統計開始年'],
      dtype='object')
In [4]:
#全国の最高気温の散らばりを見てみるが、これだけではよくわからない
temperature = df['今日の最高気温(℃)']
print("最高気温")
print(temperature)
 
最高気温
0      23.8
1      23.8
2      20.7
3      24.4
4      24.1
5      24.1
6      24.8
7      21.9
8      24.6
9      28.0
10     26.5
11     29.5
12     28.7
13     29.1
14     27.2
15     28.1
16     27.8
17     28.5
18     26.8
19     28.7
20     26.2
21     27.3
22     26.6
23     27.7
24     28.9
25     30.1
26     29.1
27     28.0
28     27.8
29     28.1
       ... 
896    30.5
897    31.5
898    31.7
899    31.0
900    31.2
901    32.3
902    30.8
903    31.6
904    31.7
905    29.4
906    32.3
907    31.0
908    31.3
909    30.0
910    32.0
911    32.1
912    31.6
913    32.1
914    31.8
915    32.1
916    31.7
917    31.6
918    31.6
919    31.8
920    31.6
921    31.9
922    32.6
923    31.5
924    33.6
925    32.1
Name: 今日の最高気温(℃), Length: 926, dtype: float64
In [15]:
#横軸は北海道〜沖縄までの地域で連番が振られているので数値に意味はない
#縦軸は気温
import matplotlib.pyplot as plt
plt.plot(temperature)
Out[15]: 
In [6]:
#合計
print("合計値:" + str(temperature.sum()))
print("データの個数:" + str(len(temperature)))
#平均値をとる
print("平均気温:" + str(temperature.mean()))
 
合計値:27288.300000000003
データの個数:926
平均気温:29.469006479481646
In [7]:
#偏差の計算
#偏差は気温から平均気温を引いた、平均値からどれくらい離れているか、という数値になる。
#例えば1行目のデータであれば、実際の気温が23.8℃で平均はさっき計算した29.46...なので 
#約-5.67℃になる。
deviation = temperature - temperature.mean()
print("それぞれの偏差")
print(deviation)
 
それぞれの偏差
0     -5.669006
1     -5.669006
2     -8.769006
3     -5.069006
4     -5.369006
5     -5.369006
6     -4.669006
7     -7.569006
8     -4.869006
9     -1.469006
10    -2.969006
11     0.030994
12    -0.769006
13    -0.369006
14    -2.269006
15    -1.369006
16    -1.669006
17    -0.969006
18    -2.669006
19    -0.769006
20    -3.269006
21    -2.169006
22    -2.869006
23    -1.769006
24    -0.569006
25     0.630994
26    -0.369006
27    -1.469006
28    -1.669006
29    -1.369006
         ...   
896    1.030994
897    2.030994
898    2.230994
899    1.530994
900    1.730994
901    2.830994
902    1.330994
903    2.130994
904    2.230994
905   -0.069006
906    2.830994
907    1.530994
908    1.830994
909    0.530994
910    2.530994
911    2.630994
912    2.130994
913    2.630994
914    2.330994
915    2.630994
916    2.230994
917    2.130994
918    2.130994
919    2.330994
920    2.130994
921    2.430994
922    3.130994
923    2.030994
924    4.130994
925    2.630994
Name: 今日の最高気温(℃), Length: 926, dtype: float64
In [8]:
#この偏差の平均を見ても0になってしまい、散らばりはわからない(プログラムで書くと桁が決められてしまうので「ほぼ」0に近い数になる)
print("偏差の平均が0になるかを確認:"+str(deviation.sum()/926))
 
偏差の平均が0になるかを確認:-4.051474778416122e-15
In [9]:
#こういう時、プラスマイナスが打ち消しあって0になるため二乗してマイナスの符号を消す、という計算をするらしく
#二乗した値で平均をとると分散という統計量が取れる。
#これはデータを二乗しているので、単位が変わってしまい、そのままでは使えません。
variance = sum(deviation * deviation)/deviation.count()
print("分散:" + str(variance))
 
分散:10.291793181383504
In [10]:
#単位を戻すために平方根をとります
#これを標準偏差といい、データの散らばり具合を表す指標になる
import numpy as np
sd = np.sqrt(variance)
print("標準偏差:" + str(sd))
 
標準偏差:3.208082477334943
In [11]:
#結果として、全国の気温は平均気温から約3.2℃散らばっていることがわかる。
#この結果だけでは、それが大きいのか小さいのかまではわからないので、例えば別の日のデータを使って比較をするなどの使い方になる。
In [12]:
import matplotlib.pyplot as plt
#データが正規分布を描く場合、
#緑の線の間に、約70%のデータが含まれ、赤い線の間に約95%のデータが含まれるらしい。
#まずはグラフをプロットしてみる
plt.hlines(temperature.mean(), 0, 926, "blue", linestyles='dashed')#平均値
plt.hlines(temperature.mean()+sd, 0, 926, "green", linestyles='dashed')#標準偏差一つ分上
plt.hlines(temperature.mean()-sd, 0, 926, "green", linestyles='dashed')#標準偏差一つ分下
plt.hlines(temperature.mean()+sd*2, 0, 926, "red", linestyles='dashed')#標準偏差二つ分上
plt.hlines(temperature.mean()-sd*2, 0, 926, "red", linestyles='dashed')#標準偏差二つ分下
plt.plot(temperature)
Out[12]:
In [13]:
#グラフでは赤い破線の中にほとんどのデータが含まれていそうに見える
#実際はどうなのかを確認してみる
#全体のデータ数は
print("件数 : " + str(temperature.count()))
#標準偏差を上限と下限に設定して、条件に当てはまるデータを抽出
print("標準偏差一つ分の範囲:" + str(len(temperature[(temperature <= temperature.mean()+sd) &(temperature >= temperature.mean()-sd)]) ))
#割合
print("割合:" + str(round(683/926*100, 1))+ "%")
#70%を超えてしまいましたが、大きくは外れていません。
 
件数 : 926
標準偏差一つ分の範囲:683
割合:73.8%
In [14]:
#実際はどうなのかを確認してみる
#全体のデータ数は
print("件数 : " + str(temperature.count()))
#標準偏差2つ分を上限と下限に設定して、条件に当てはまるデータを抽出
print("標準偏差2つ分の範囲:" + str(len(temperature[(temperature <= temperature.mean()+sd*2) &(temperature >= temperature.mean()-sd*2)]) ))
#割合
print("割合:" + str(round(876/926*100, 1))+ "%")
#95%くらいのデータが含まれています。
 
件数 : 926
標準偏差2つ分の範囲:876
割合:94.6%
In [18]:
#23.1℃以下、もしくは35.9℃以上の気温だった地域は7/24時点では全国的に見て外れ値(全国平均からすると特殊)
print("下限:"+ str(temperature.mean()-sd*2))
print("上限:"+ str(temperature.mean()+sd*2))
a = df[(df['今日の最高気温(℃)'] < temperature.mean()-sd*2) |  (df['今日の最高気温(℃)'] > temperature.mean()+sd*2) ] 
 
下限:23.05284152481176
上限:35.88517143415153
In [23]:
#残りの5%の地域
a[['都道府県','地点']]
Out[23]:
都道府県 地点
2 北海道宗谷地方 礼文(レブン)
7 北海道宗谷地方 沓形(クツガタ)
39 北海道留萌地方 焼尻(ヤギシリ)
46 北海道石狩地方 厚田(アツタ)
52 北海道石狩地方 恵庭島松(エニワシママツ)
53 北海道石狩地方 支笏湖畔(シコツコハン)
54 北海道石狩地方 千歳(チトセ)
63 北海道空知地方 長沼(ナガヌマ)
70 北海道後志地方 蘭越(ランコシ)
75 北海道後志地方 黒松内(クロマツナイ)
104 北海道根室地方 根室(ネムロ)
105 北海道根室地方 納沙布(ノサップ)
106 北海道根室地方 厚床(アットコ)
108 北海道釧路地方 弟子屈(テシカガ)
110 北海道釧路地方 標茶(シベチャ)
111 北海道釧路地方 鶴居(ツルイ)
112 北海道釧路地方 中徹別(ナカテシベツ)
113 北海道釧路地方 榊町(サカキマチ)
114 北海道釧路地方 鶴丘(ツルオカ)
115 北海道釧路地方 太田(オオタ)
116 北海道釧路地方 白糠(シラヌカ)
117 北海道釧路地方 釧路(クシロ)
118 北海道釧路地方 知方学(チッポマナイ)
120 北海道十勝地方 ぬかびら源泉郷(ヌカビラゲンセンキョウ)
121 北海道十勝地方 上士幌(カミシホロ)
124 北海道十勝地方 新得(シントク)
125 北海道十勝地方 鹿追(シカオイ)
128 北海道十勝地方 帯広(オビヒロ)
129 北海道十勝地方 池田(イケダ)
130 北海道十勝地方 浦幌(ウラホロ)
135 北海道十勝地方 大津(オオツ)
137 北海道十勝地方 広尾(ヒロオ)
141 北海道胆振地方 森野(モリノ)
142 北海道胆振地方 苫小牧(トマコマイ)
143 北海道胆振地方 大岸(オオキシ)
144 北海道胆振地方 白老(シラオイ)
145 北海道胆振地方 鵡川(ムカワ)
146 北海道胆振地方 伊達(ダテ)
147 北海道胆振地方 登別(ノボリベツ)
148 北海道胆振地方 室蘭(ムロラン)
150 北海道日高地方 日高門別(ヒダカモンベツ)
155 北海道日高地方 浦河(ウラカワ)
156 北海道日高地方 えりも岬(エリモミサキ)
157 北海道渡島地方 長万部(オシャマンベ)
158 北海道渡島地方 八雲(ヤクモ)
160 北海道渡島地方 川汲(カックミ)
167 北海道檜山地方 せたな(セタナ)
168 北海道檜山地方 今金(イマカネ)
353 栃木県 奥日光(オクニッコウ)(日光(ニツコウ))
512 岐阜県 多治見(タジミ)

7/24の全国的な気温の散らばりや、データの特徴を把握しました。

スポンサーリンク

  • このエントリーをはてなブックマークに追加
  • LINEで送る

SNSでもご購読できます。

コメントを残す

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください