LoginSignup
3
4

More than 3 years have passed since last update.

【無相関の検定】棄却有無の境界線を出してみた

Posted at

はじめに

統計の勉強で様々な計算式を覚えていく過程で、無相関の検定がなかなか覚えられないので、式を睨んでいました。
そして、気になることがあったので、Pythonで計算させて結果を描画してみました。

  • 環境
    • Windows-10-10.0.18362-SP0
    • Python 3.7.6
    • pip 19.3.1
    • pandas 1.0.3
    • matplotlib 3.1.2
    • seaborn 0.10.0
    • numpy 1.18.1
    • scipy 1.4.1

無相関の検定

標本から得られた相関係数から「母集団にも同様の相関がある」と言えるかどうかを検定するもの。

  • 帰無仮説H0 : 母相関係数は0である (同様の相関はない)

  • 対立仮説H1 : 母相関係数は0ではない

下記の式から、統計量$t$を求め、$p$値を出します。統計量$t$に対する自由度$ν$は$n-2$です。

t = \frac{|r| \sqrt{n - 2}}{\sqrt{1 - r^2}}

有意水準$a$を0.05とした場合は、両側検定で、$p$値0.025点を見れば良いことになります。



... なかなか使わないこともあって、この式が覚えられないんですよ。
ただ、「これってn(サンプルサイズ)が大きければt値大きくなるじゃん、結局はサンプルサイズじゃん!!」と思ったので、サンプルサイズと相関係数を総当りさせて、どのあたりまでなら帰無仮説が棄却されないのかを見てみました。

準備

#データづくりに使用
import pandas as pd
import numpy as np
import math
from scipy import stats
import itertools

#グラフ描画に使用
import matplotlib.pyplot as plt
import seaborn as sns
from mpl_toolkits.mplot3d import Axes3D


%matplotlib inline


plt.style.use('seaborn-darkgrid')
plt.rcParams['font.family'] = 'Yu Gothic'
plt.rcParams['font.size'] = 20


#相関係数(coef)とサンプルサイズ(n)を入れたら、t値(t)、自由度(df)、p値(p)が返る関数を作成。
def Uncorrelated(coef, n):
    t = (np.abs(coef) * math.sqrt( (n - 2) ) ) / (math.sqrt( ( 1 - (coef**2) ) ) )
    df = (n - 2)
    p = np.round(( 1 - stats.t.cdf(np.abs(t), df) ), 3) #p値丸めてます。
    return coef, n, t, df, p


#サンプル数 10から1000まで10刻み
samplesizes = np.arange(10, 1001, 10)

#相関係数 -0.99から0.99まで0.01刻み
coefficients = np.linspace(-0.99, 0.99, 199)
#print(coefficients)

#上の2つをCrossjoin(直積)
c_s = list(itertools.product(coefficients, samplesizes) )

#相関係数とサンプルサイズを格納したリストをUncorrelated関数へ入れ、帰ってきたものをPandasでDataFrame化
df_prelist = []
for i in range(len(c_s)): 
    df_prelist.append(Uncorrelated(c_s[i][0],c_s[i][1])) 

#準備は完成
df = pd.DataFrame(df_prelist,columns=['coef','sample_size','t','df','p_value'])

dfはこんなかんじ

df

image.png

df.sample(10)

image.png

相関係数-0.99~0.99,サンプルサイズ10~1000までに対しての無相関の検定のt値、自由度、p値が入っています。

グラフ描画

fig = plt.figure( figsize=(16, 12) )
ax = Axes3D(fig)
cm = plt.cm.get_cmap('RdYlBu')
mappable = ax.scatter( np.array(df['coef']), np.array(df['sample_size']), np.array(df['p_value']), c=np.array(df['p_value']), cmap=cm)
fig.colorbar(mappable, ax=ax)
ax.set_xlabel('相関係数', labelpad=15)
ax.set_ylabel('サンプルサイズ', labelpad=15)
ax.set_zlabel('p値', labelpad=15)
plt.savefig('3次元グラフ.png', bbox_inches='tight', pad_inches=0.3)
plt.show()

3次元グラフ.png

...青色に近づくほど、p値が高く、棄却されないのですが・・・分かりづらいですね

Judgeカラムを作成し、p値が0.025よりも大きいものを、「H0を棄却しない」としてDataFrameを作り直しました。

#p_valueが0.025以上なら、`H0を棄却しない`をつける
df['judge'] = 'H0を棄却する'
for index, series in df.query('p_value > 0.025').iterrows():
    df.at[index, 'judge'] = 'H0を棄却しない'


#グラフ再描画
grid = sns.FacetGrid( df, hue = 'judge', height=10 )
grid.map(plt.scatter, 'coef', 'sample_size')
grid.add_legend(title='判定')
plt.ylabel('サンプルサイズ')
plt.xlabel('相関係数')
plt.title('相関係数xサンプルサイズ 無相関検定の棄却有無', size=30)

#赤線を引く
plt.vlines(df[df['judge'] == 'H0を棄却しない']['coef'].max(), -50, 50, color='red', linestyles='dashed')
plt.vlines(df[df['judge'] == 'H0を棄却しない']['coef'].min(), -50, 50, color='red', linestyles='dashed')
plt.annotate('|' + str(df[df['judge'] == 'H0を棄却しない']['coef'].max().round(2) ) + '|より外側は、n=10以上なら全て棄却する',
            xy=(df[df['judge'] == 'H0を棄却しない']['coef'].max(), 80), size=15, color='black')
plt.savefig('2次元グラフ.png', bbox_inches='tight', pad_inches=0.3)
plt.show()

2次元グラフ.png

なるほど、標本の相関係数が絶対値0.62より大きければ、n=10でも帰無仮説H0を棄却して、「母相関係数は0ではない」が採択される($a=0.05$)ということですね!





...ちなみに、「計算式を覚える」という当初の目的はこの記事を書いて覚えました:upside_down:

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4