統計学入門① 基本統計量とPandas

f:id:monozukuri-bu:20190513215343j:plain

よく訓練されたPython信者、モノづくり部のkibaraです。

今回から数回に分けて、Pythonを使って、みんなで統計学を勉強していきたいと思います。
なお、Pythonの基本文法はご存じの前提で進みますので、ご了承ください。

Python環境

以下の環境で動作確認しています。

Python 3.7
Pandas 0.23.4

また、今回はコチラのサンプルデータを利用します。

生徒ID 国語 数学 理科 社会 英語
ST001 50 50 50 50 50
ST002 80 92 76 88 96
ST003 25 14 38 16 26
ST004 60 75 58 48 52
ST005 100 0 0 0 0

Pandasを使って読み込んでおきます。

import pandas as pd

df = pd.read_csv("sample.csv")
print(df.head())
###################################################
#    生徒ID   国語    数学   理科   社会    英語
# 0  ST001     50     50     50     50     50
# 1  ST002     80     92     76     88     96
# 2  ST003     25     14     38     16     26
# 3  ST004     60     75     58     48     52
# 4  ST005    100    100     50      0      0

基本統計量

統計量とは、大まかにいうと「目的に応じた手法によって、データの特徴を要約した値」です。
統計量にもいろいろあるようですが、今回は入門編ということで、
基本統計量と呼ばれるものを勉強してみます。

具体的には「最大値・最小値」「平均値」「中央値」「標準偏差」などが挙げられます。
これらについて、簡単に見てみましょう。

最大値・最小値

言わずもがな、データの中で一番大きな値、一番小さな値です。
サンプルデータで、各教科の最高点、最低点を見てみましょう。

print(df.iloc[:, 1:].min())
# 国語    25
# 数学    14
# 理科    38
# 社会     0
# 英語     0

print(df.iloc[:, 1:].max())
# 国語    100
# 数学    100
# 理科     76
# 社会     88
# 英語     96

※ilocで生徒ID列を削っています。

min()で最小値、 max()で最大値を取得できます。

国語と数学は満点がいる反面、社会と英語は0点がいますね。
最大値と最小値を見ると、データの中で値の範囲がわかります。

平均値

加重平均や調和平均など、実は色々な種類のある平均値ですが、 ここでは一般的な算術平均(相加平均)のみ扱います。

算術平均は以下の式で表現されます。

 \displaystyle
  x=\frac{x_1+x_2+x_3+...+x_n}{n}

全ての要素を足し合わせ、要素数で割った値です。
小学校で習ったやつですね。

ST001 = df.loc[0][1:]
print(ST001.mean())
# (50 + 50 + 50 + 50 + 50) / 5
# -> 50.0

ST005 = df.loc[4][1:]
print(ST005.mean())
# (100 + 100 + 50 + 0 + 0) / 5
# -> 50.0

mean()を使うと、簡単に算術平均を求めることができます。

平均値は全体の真ん中あたりの値がわかるためテストの平均点などでよく使われる要約ではあるのですが、データのバラつき具合までは判断できません。
ST001さんはどの教科もバランスよく50点取っているのに対し、ST005さんは100点だったり0点だったりと、バラつきがありますが、上の例では、どちらも平均値は50になってしまっています。

中央値

中央値は、データを昇順(降順)に並べたときに中央に位置する値です。
5件のデータがあったとき、3番目のデータが中央値になります。

ST002 = df.loc[1][1:]
print(ST002.median())
# 80, 92, 76, 88, 96
# -> 88.0

中央値はmedian()です。

中央値は「データを一列に並べたときに真ん中の位置にある値」になりますので、
平均値とは値が異なる場合があります。

上記の例ではデータ件数が奇数だったので、真ん中の値がそのまま中央値になりました。
では、データ件数が偶数の場合、中央値はどうなるのでしょう。

ST002 = df.loc[1][2:]
print(ST002.median())
# 92, 76, 88, 96
# -> 90

ST002さんの国語の点数を削って4科目だけにしたところ、中央値は90となりました。
これは、データを昇順に並べた76, 88, 92, 96の、真ん中2つの値の平均値をとって、
(88 + 92) / 2 = 90となっています。

標準偏差

標準偏差は、データのバラつき具合を表しています。
データが平均値からどれぐらい離れているのかを知ることができます。

標準偏差の計算にはいくつかのステップがあるので、順を追ってみていきましょう。
今回は理科の点数について、標準偏差を求めてみます。

まず、標準偏差を求めたいデータの、平均値を求めます。

# 理科の点数
science = df.iloc[:, 3]

# STEP1 平均値を求める
science_mean = science.mean()
print(science_mean)
# 54.4

次に、各データそれぞれと、平均値との差を求めます。

# STEP2 データと平均値の差を求める
science_dev = science - science_mean
print(science_dev)
# 0    -4.4
# 1    21.6
# 2   -16.4
# 3     3.6
# 4    -4.4

これで、各データが平均値とどれだけ離れているのかがわかりました。
この値を偏差を呼びます。

しかしこれでは、理科の点数のバラつき具合がわかったとは言えません。

偏差を平均すれば「データが平均値と比べてどれだけ離れているか」を要約できそうですが、
実際に偏差を合計してみると(-4.4) + 21.6 + (-16.4) + 3.6 + (-4.4) = 0となってしまいます。
偏差の合計は必ず0となるため、偏差の平均も0となるのです。

そこでデータをよく見てみると、どうやらマイナスが悪さをしていそうです。
マイナスを消すために2乗してから、平均を求めてみます。

# STEP3 偏差の二乗を平均する
science_var = (science_dev ** 2).mean()
print(science_var)
# 157.44000000000003

この値は分散と呼びます。

これで「データが平均値と比べてどれぐらい離れているのか」という
バラつき具合の要約が出来ました。

でもちょっと待ってください。
そういえば、バラつき具合の平均を取るために偏差を2乗していましたので、
元のデータと単位があっていません。

元のデータと単位を合わせておく必要がありますので、分散の平方根を求めます。

import math

# STEP4 分散の平方根√を求める
science_std = math.sqrt(science_var)
print(science_std)
# 12.547509713086498

ようやくたどり着きました。
これが標準偏差と呼ばれる値です。

理科の点数は、平均点54.4±12.5点ぐらいバラついている、ということがわかりました。
「平均値との差分を平均した値」になっているので、
必ずしも54.4±12.5の範囲に収まっているわけではないことは、ご注意ください。

基本統計量の算出

ここまで、ごく一部ではありますが、代表的な基本統計量についてみてきました。
標準偏差の計算方法も学びましたが、この計算を毎回やるのはさすがに面倒です。

楽をする方法も、もちろんあります。
そう、Pythonならね。(?)

print(df.describe())
#          国語         数学        理科       社会       英語
# count    5.000000    5.000000   5.000000   5.000000   5.00000  # データ件数
# mean    63.000000   66.200000  54.400000  40.400000  44.80000  # 平均値
# std     28.635642   34.902722  14.028542  34.070515  35.56965  # 標準偏差
# min     25.000000   14.000000  38.000000   0.000000   0.00000  # 最小値
# 25%     50.000000   50.000000  50.000000  16.000000  26.00000  # 第1四分位数
# 50%     60.000000   75.000000  50.000000  48.000000  50.00000  # 中央値
# 75%     80.000000   92.000000  58.000000  50.000000  52.00000  # 第3四分位数
# max    100.000000  100.000000  76.000000  88.000000  96.00000  # 最大値

describe()を使用することにより、今回紹介したような基本統計量を
一覧でまとめて出力させることができます。

ここで、理科の標準偏差の値が違うことに注意してください。
このdescribe()で出力される標準偏差は、不偏標準偏差という、
今回紹介したものとは求め方が若干異なる標準偏差になっています。

今回紹介した標準偏差を求めるには、以下のようにすればOKです。

# 標準偏差を求める std
print(science.std(ddof=0))
# 12.547509713086498

# 分散を求める var
print(science.var(ddof=0))
# 157.44000000000003

分散はvar()標準偏差std()で簡単に求めることができます。
ポイントは、ddof=0と指定しているところです。

ddofを指定しないとデフォルト値1が使用され、不偏分散、不偏標準偏差になります。

# 不偏分散を求める
print(science.var())
# 196.80000000000004

# 不偏標準偏差を求める
print(science.std())
# 14.028542333400146

これに関する詳しい話は、また別の記事で書ければと思っております。

まとめ

今回は、基本統計量について勉強しました。
今回紹介しきれなかった四分位数や箱ひげ図、ヒストグラムなどについても、
データの特徴を掴むためには必要な技術なので、次の記事で学んでいければと思います。