2019年5月3日金曜日

[Statistics] III データ分析 記述統計:多変量データ編

Pythonで学ぶあたらしい統計学の教科書のまとめやコードを実行してみた際のメモです.

多変量データ:複数の変数が組み合わされたデータのこと.
多変量データでは,1変量データと集計の方法が異なります.

整然データ
整然データ:Wickham(2014)によって提唱された,分析がしやすくなるように整理された表形式のデータのこと.
整然データは以下の4つの特徴を持ち,意味と構造が対応するという特徴を持ちます(e.g. 値とセル,変数と列,観測と行という対応がある).
  1. 個々の値が1つのセルをなす.
  2. 個々の変数が1つの列をなす.
  3. 個々の観測が1つの行をなす.
  4. 個々の観測ユニットの類型が1つの表をなす.
分析者が整然データを用いるメリットは,複雑な集計を統一的な処理で行えることで,整然データは,ソフトウェアでの扱いやすさを考慮したデータの形式と言えます.

雑然データ:整然データではないデータの形式のこと.雑然データは,行に変数としての意味を持たせてしまう傾向がある.

多変量データの管理
整然データの形式で管理されている場合は,pandasデータフレームを用いることで,データの管理を行うことができます.

まずは,pandasとscipyをインポートします.
>>> import pandas as pd
>>> import scipy as sp

魚の種類別にまとめた体長データを読み込んで,表示してみます(Pythonを実行しているディレクトリに,3-2-1-fish_multi.csv*ファイルが存在する前提です).
>>> fish_multi = pd.read_csv("3-2-1-fish_multi.csv")
>>> print(fish_multi)
  species  length
0       A       2
1       A       3
2       A       4
3       B       6
4       B       8
5       B      10

グループ別の統計量
多変量データにおいて統計量を求める場合は,抽出〜抽出されたデータで統計量を計算する流れで分析を行うのが1つの方法だが,若干の手間がかかってしまいます.
そこで,以下のように,グループでまとめる groupby という関数があるので,それを用いると短いコードで実行することが可能です.
以下の例では,1行目で種類毎のグループを作って,2行目でグループ毎の平均値を求めて表示しています.
>>> group = fish_multi.groupby("species")
>>> print(group.mean())
         length
species        
A             3
B             8

標準偏差も同様に計算できます.
>>> print(group.std(ddof = 1))
         length
species        
A           1.0
B           2.0

平均値,標準偏差や四分位点をまとめて表示することもできます.
>>> group.describe()
        length                                    
         count mean  std  min  25%  50%  75%   max
species                                           
A          3.0  3.0  1.0  2.0  2.5  3.0  3.5   4.0
B          3.0  8.0  2.0  6.0  7.0  8.0  9.0  10.0

クロス集計表
整然データを読み込んだ上で,それをクロス集計表に変換してみます.
まずは,データの読み込みを行います(データの中身は店別,色別の靴の売り上げデータで,Pythonを実行しているディレクトリに,3-2-2-shoe.csv**ファイルが存在する前提です).
>>> shoes = pd.read_csv("3-2-2-shoes.csv")
>>> print(shoes)
   store color  sales
0  tokyo  blue     10
1  tokyo   red     15
2  osaka  blue     13
3  osaka   red      9

ここで,pandasのpivot_table関数を使えば,様々な集計処理を行うことができます.
>>> cross = pd.pivot_table(
...     data = shoes,
...     values = "sales", 
...     aggfunc = "sum", 
...     index = "store", 
...     columns = "color"
... )
>>> print(cross)
color  blue  red
store           
osaka    13    9
tokyo    10   15

2行目でデータの指定,3行目で集計対象を,4行目で集計のための関数を指定しています.5, 6行目はクロス集計表の行と列の指定です.

共分散(Covariance)
共分散:2つの連続型の変数の関係性を見る時に使われる統計量.
共分散は以下のように解釈します.
  • 共分散が 0よりも大:片方の変数が大きい値を取れば,もう片方も大きくなる.
  • 共分散が 0よりも小:片方の変数が大きい値を取れば,もう片方は小さくなる.
  • 共分散がちょうど 0:変数同士に関係性が見られない.
変数$x, y$の共分散 $\mathrm{Cov} (x, y)$は,以下のように計算されます.
$\mathrm{Cov} (x, y) = \cfrac{1}{N} \sum_{i = 1}^{N} ( x_{i} - \mu_{x} ) ( y_{i} - \mu_{y} )$
ただし,$\mu_{x}$,$\mu_{y}$は各々変数$x, y$の平均値です.また,$N$はサンプルサイズです.
参考:分散の式
$\sigma^{2} = \cfrac{1}{N} \sum_{i = 1}^{N} ( x_{i} - \mu)^{2}$
分散は,二乗されているので$( x_{i} - \mu ) ( x_{i} - \mu )$というように,同じものを2回掛け合わせていました.共分散は変数$x, y$を片方ずつ使ういます.

共分散の数式は,もしも0より大きな共分散を持っていた時,片方の変数$x$が平均より大きな値となった場合は,もう片方の変数$y$も平均より大きくなっていると期待できます.また,片方の変数$x$が平均より小さい値となった場合は,もう片方の変数$y$も平均より小さくなっていると期待できます.逆に共分散が0よりも小さかった場合は,片方の変数$x$が平均よりも大きな値となった場合は,もう片方の変数$y$は平均よりも小さくなっており,片方の変数$x$が平均よりも小さい値となった場合は,もう片方の変数$y$は平均よりも大きい値になると考えられます.

分散と同じように共分散でも分母は$N-1$を用いる場合があります.
$\mathrm{Cov} (x, y) = \cfrac{1}{N} \sum_{i = 1}^{N} ( x_{i} - \mu_{x} ) ( y_{i} - \mu_{y} )$

分散共分散行列
分散共分散行列:複数の変数において,分散と共分散の一覧を下式のように行列の形にまとめたもの.
$\mathrm{Cov} (x, y) = \begin{bmatrix} \sigma_{x}^{2}  &\mathrm{Cov}(x, y)\\ \mathrm{Cov}(x, y) &\sigma^{2} \end{bmatrix}$
ただし,$\sigma_{x}^{2}, \sigma_{y}^{2}$は各々,変数の分散です.

共分散
まずは,共分散の計算をするためにサンプルデータを読み込みます(Pythonを実行しているディレクトリに,3-2-3-cov.csv***ファイルが存在する前提です).
>>> cov_data = pd.read_csv("3-2-3-cov.csv")
>>> print(cov_data)
      x   y
0  18.5  34
1  18.7  39
2  19.1  41
3  19.7  38
4  21.5  45
5  21.7  41
6  21.8  52
7  22.0  44
8  23.4  44
9  23.8  49

共分散を計算するために使う要素をあらかじめ計算します.
まずは,データの取り出しです.
>>> x = cov_data["x"]
>>> y = cov_data["y"]
サンプルサイズを求めます.
>>> N = len(cov_data)
平均値を計算します.
>>> mu_x = sp.mean(x)
>>> mu_y = sp.mean(y)

これらの計算結果をもとにして共分散を計算します.
>>> cov_sample = sum((x - mu_x) * (y - mu_y)) / N
>>> cov_sample
6.9060000000000015
分母を $N-1$とした共分散を計算します.

>>> cov = sum((x - mu_x) * (y - mu_y)) / (N - 1)
>>> cov
7.673333333333336


分散共分散行列
scipyのcov関数を用いると短いコードで分散共分散行列の計算が可能です.
>>> sp.cov(x, y, ddof = 0)
array([[ 3.2816,  6.906 ],
       [ 6.906 , 25.21  ]])
分母を$N-1$とした分散共分散行列を求める場合は,ddof = 1 と設定します.

>>> sp.cov(x, y, ddof = 1)
array([[ 3.64622222,  7.67333333],
       [ 7.67333333, 28.01111111]])


ピアソンの積率相関係数
変数$x, y$において,下式のように計算される$\rho_{xy}$をピアソンの積率相関係数と言います.一般的に相関係数という場合は,このピアソンの積率相関係数を指していることがほとんどです.
$\rho = \cfrac{Cov (x, y)}{\sqrt{\sigma_{x}^{2} \sigma_{y}^{2}}}$
上式は,共分散を最大値1,最小値-1に標準化したものとみなすことができます.
共分散は便利な指標なのですが,最大値や最小値がいくらになるのかはわかりません(例えば,元のデータの単位が変われば,共分散の値も変わる).なので,-1 〜 +1の範囲に入るように補正したものと考えるとわかりやすいかもしれません.

相関行列
相関行列:複数の変数において,相関係数の一覧を下式のように行列の形式でまとめたもの.
変数$x, y$の相関行列は以下のようになります.
Cov$(x, y) = \begin{bmatrix} 1  &\rho_{x y}\\ \rho_{x y} &1 \end{bmatrix}$

相関係数を計算してみます.
まずは分散を計算します.
>>> sigma_2_x = sp.var(x, ddof = 1)
>>> sigma_2_y = sp.var(y, ddof = 1)
続いて相関係数を計算します.
>>> rho = cov / sp.sqrt(sigma_2_x * sigma_2_y)
>>> rho
0.7592719041137088

分母と分子が同じ値で割られていることになるので,分散・共分散の計算式には$N$を使っても$N-1$を使っても相関係数は変わらないことを確認してみます.
まずは分散の計算です.
>>> sigma_2_x_sample = sp.var(x, ddof = 0)
>>> sigma_2_y_sample = sp.var(y, ddof = 0)
続いて相関係数の計算です.
>>> cov_sample / sp.sqrt(sigma_2_x_sample * sigma_2_y_sample)
0.7592719041137088


scipyのcorrcoef関数を用いると短いコードで相関行列を計算することができます.
>>> sp.corrcoef(x, y)
array([[1.       , 0.7592719],
       [0.7592719, 1.       ]])

上記の事柄をJupiter Notebookで実行した結果はGitHubで公開しています.

3-2-1-fish_multi.csv の中身
species,length
A,2
A,3
A,4
B,6
B,8
B,10

** 3-2-2-shoes.csv の中身
store,color,sales
tokyo,blue,10
tokyo,red,15
osaka,blue,13
osaka,red,9

*** 3-2-3-cov.csv の中身
x,y
18.5,34
18.7,39
19.1,41
19.7,38
21.5,45
21.7,41
21.8,52
22,44
23.4,44
23.8,49

0 件のコメント :

コメントを投稿