俺、サービス売って家買うんだ

Swift, Kotlin, Vue.js, 統計, GCP / このペースで作ってればいつか2-3億で売れるのがポっと出来るんじゃなかろうか

相関分析の時に四分位範囲(IQR)で外れ値を見つける(Python)

2変数の間に関係性があるかどうか調べる時に、ピアソンの相関係数を扱うことは非常に多いと思います。

しかし御存知の通り、相関係数は扱うデータのサンプルの外れ値に大きく影響を受けます。 テストの問題を解くだけなら良いのですが、実際に分析していると外れ値の処理(データクレンジング)や、正規分布の検定 をしなければなりません。

今回は、変数間の相関を分析する際の、四分位範囲(IQR)を用いた外れ値の対応について、Pythonを用いて書いていきます。

目次:相関を分析するための手順

  1. そもそも外れ値とは?
  2. まずはサンプルデータと散布図の作成
  3. 相関係数の計算と、四分位範囲を用いたはずれ値の検出

1. そもそも外れ値とは?

外れ値とは?

外れ値とは、統計において他の値から大きく離れた値のことを言います。
(例:身長2mのバスケット選手は1万人に1人で、平均身長170cm から大きく離れているため、外れ値といえます)

2. まずはサンプルデータと散布図の作成

Rからサンプルデータを取ってくる。

Python (NumpyとかSchipyとか)には良いサンプルデータがないんですよね。
なのでRからとってきちゃおうと思います。

#RからCSVにしてデータを持ってくる
> data = data.frame(women)
> write.table(data,  'women.csv', sep=',', quote=FALSE, col.names=TRUE)

でCSVエクスポートするとアメリカの女性の身長と体重のデータをゲットできます。その後、Pythonにインポートしましょう。
データフレーム内に取り込むのが吉な気がします。

women = pd.read_csv('/Users/hayato1986/Desktop/women.csv')

それでは散布図を書いてみましょう。前回の記事でも言及しましたが、まずはグラフや図を書いて全体像をつかむのが非常に大事です。

height = women.ix[:,1]
weight = women.ix[:,0]
plt.scatter(height, weight)

f:id:hayato1986:20160322205627p:plain

完璧なグラフですねw ためしに相関係数を求めてみましょう。

women.corr()


height  weight
height  1.000000   0.995495
weight  0.995495   1.000000

圧倒的相関です。0.8あれば強い相関があると言われる世の中で0.99以上の相関。

外れ値の混入と検出

ここに外れ値を入れて、もう一度散布図を書いてみます。

s1 = pd.Series([165,165],index=['weight','height'],name=16) #外れ値その1
s2 = pd.Series([120,200],index=['weight','height'],name=16) #外れ値その2

women = women.append(s1)
women = women.append(s2)

weight = women.ix[:,1]
height = women.ix[:,0]

plt.scatter(women.ix[:,0], women.ix[:,1])

f:id:hayato1986:20160414112107p:plain

右2つの点が後から入れた外れ値です。

3. 相関係数の計算と、四分位範囲を用いたはずれ値の検出

さて、データが整ったので実際に相関係数の計算と外れ値を検出していきましょう。

women.corr()
>0.129859

相関係数は0.12と出ました。通常ならここで相関がない、と判断してしまうのですが、外れ値の存在を考慮に入れていません。

一番かんたんなのは、グラフから目見で外れ値を除いていくことです。やっぱり統計にはグラフ描くのが凄く大切です。 今回の例では、明らかに塊から外れた右の2つを除くことができます。

f:id:hayato1986:20160414112052p:plain

その他にも統計ではお決まりの、偉い人が考えたよくわからないけど役に立つスミルノフ・グラブス検定方法があります。
ツールとしてではなく、趣味としてでなければその成り立ちや理由を深掘りする必要ないと思います。あくまで便利な手段として拝借しましょう。
注意しなければならないのは、正規分布であると仮定されている必要があることです。

四分位範囲を用いたはずれ値の検出

こちらは正規分布である必要もなく、計算もわかりやすいのでおすすめです。 四分位範囲に1.5を掛けて「第一四分位数から引いた値」と「第三四分位数に足した値」の範囲から外れたものを外れ値とします。
身長と体重の両方をIQRにかけて、範囲に収まらない値を削除していきましょう。

#IQRで外れ値の検出
from scipy import stats

###体重###
#四分位範囲を計算
weight_q1 = stats.scoreatpercentile(weight, 25) #第一四分位数(=25パーセンタイル)
weight_q3 = stats.scoreatpercentile(weight, 75) #第三四分位数(=75パーセンタイル)
weight_iqr = weight_q3 - weight_q1 #四分位範囲

#外れ値の範囲を計算する
weight_iqr_min = weight_q1 - (weight_iqr) * 1.5 #第一四分位数 から四分位範囲(iqr*1.5)を引き算。
weight_iqr_max = weight_q3 + (weight_iqr) * 1.5 #第一四分位数 から四分位範囲(iqr*1.5)を。

#範囲から外れている値を除く
women = women[weigth < weight_iqr_max]


###身長###
#四分位範囲を計算
height_q1 = stats.scoreatpercentile(height, 25)#第一四分位数(=25パーセンタイル)
height_q3 = stats.scoreatpercentile(height, 75)#第三四分位数(=75パーセンタイル)
height_iqr = height_q3 - height_q1 #四分位範囲

#外れ値の範囲を計算する
height_iqr_min = height_q1 - (height_iqr) * 1.5 #第一四分位数 から四分位範囲(iqr*1.5)を引き算。
height_iqr_max = height_q3 + (height_iqr) * 1.5 #第一四分位数 から四分位範囲(iqr*1.5)を。

#範囲から外れている値を除く
women = women[height < height_iqr_max]

相関係数を確認すると、

women.corr()
>0.995495   

(๑•̀ㅂ•́)و✧ぐっ
しっかり外れ値を検出できてますね。

まとめ

いかがでしたでしょうか?相関分析をするときの外れ値がすごく大事だとわかったと思います。
統計の基礎をさくっと学びたい方はこちらがおすすめです。

完全独習 統計学入門

完全独習 統計学入門

オラッオラッヽ(^。^)ノ