In [1]:
%matplotlib inline
In [2]:
# -*- coding:utf-8 -*-
from __future__ import print_function
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.stats.diagnostic as smsdia
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
In [3]:
# データ読み込み
data = pd.read_csv('example/k0601.csv')
In [4]:
# 説明変数設定
X = data['X']
X = sm.add_constant(X)
X
Out[4]:
In [5]:
# 被説明変数設定
Y = data['Y']
Y
Out[5]:
In [6]:
# OLSの実行(Ordinary Least Squares: 最小二乗法)
model = sm.OLS(Y,X)
results = model.fit()
print(results.summary())
In [7]:
# グラフ生成
plt.plot(data["X"], data["Y"], 'o', label="data")
plt.plot(data["X"], results.fittedvalues, label="OLS")
plt.xlim(min(data["X"])-1, max(data["X"])+1)
plt.ylim(min(data["Y"])-1, max(data["Y"])+1)
plt.title('Example6-1')
plt.legend(loc=2)
plt.show()
In [8]:
# 残差(residual)
results.resid
Out[8]:
In [9]:
# 被説明変数(endogenous ) http://statsmodels.sourceforge.net/devel/endog_exog.html
results.model.endog
Out[9]:
In [10]:
# 説明変数(exogenous)
results.model.exog
Out[10]:
BP統計量を計算するにあたって、statsmodels.stats.diagnostic.het_breushpagan()を使う。
-----
statsmodels.stats.diagnostic.het_breushpagan(resid, exog_het)
Parameters:
resid : arraylike, (nobs,)
For the Breush-Pagan test, this should be the residual of a regression.
exog_het : array_like, (nobs, nvars)
This contains variables that might create data dependent heteroscedasticity.
Returns:
lm : float
lagrange multiplier statistic
lm_pvalue :float :
p-value of lagrange multiplier test
fvalue : float
f-statistic of the hypothesis that the error variance does not depend on x
f_pvalue : float
p-value for the f-statistic
-----
In [11]:
smsdia.het_breushpagan(results.resid, results.model.exog)
Out[11]:
これの1つ目がBP統計量で、2つ目がP値。
見やすいように整えておく。
In [12]:
BP = smsdia.het_breushpagan(results.resid, results.model.exog)
print('Breusch-Pagan test : ')
print('BP = ', BP[0])
print('p-value = ', BP[1])
よって、 BP=0.14630.1463となり0に近い値であることがわかる。
P値は0.702となり有意水準10%でも帰無仮説BP=0を棄却することはできず、均一分散であると結論することができます。
データを読み込みます。
In [13]:
data = pd.read_csv('example/k0602.csv')
In [14]:
# 説明変数設定
X = data['X']
X = sm.add_constant(X)
X
Out[14]:
In [15]:
# 被説明変数設定
Y = data['Y']
Y
Out[15]:
In [16]:
# OLSの実行(Ordinary Least Squares: 最小二乗法)
model = sm.OLS(Y,X)
results = model.fit()
print(results.summary())
In [17]:
# グラフ生成
plt.plot(data["X"], data["Y"], 'o', label="data")
plt.plot(data["X"], results.fittedvalues, label="OLS")
plt.xlim(min(data["X"])-1, max(data["X"])+1)
plt.ylim(min(data["Y"])-1, max(data["Y"])+1)
plt.title('Example6-2')
plt.legend(loc=2)
plt.show()
In [18]:
BP = smsdia.het_breushpagan(results.resid, results.model.exog)
print('Breusch-Pagan test : ')
print('BP = ', BP[0])
print('p-value = ', BP[1])
P値は0.003より有意水準1%でも帰無仮説BP=0を棄却することができ、不均一分散であると結論することができます。
先ほど読み込んだ「k0602.csv」のデータから変数の対数化を行います。
dataの中に新しいコラム「lnX」「lnY」を追加します。
In [19]:
data["lnX"] = np.log(data["X"])
data["lnY"] = np.log(data["Y"])
data
Out[19]:
In [20]:
# 説明変数設定
X = data['lnX']
X = sm.add_constant(X)
X
Out[20]:
In [21]:
# 被説明変数設定
Y = data['lnY']
Y
Out[21]:
In [22]:
# OLSの実行(Ordinary Least Squares: 最小二乗法)
model = sm.OLS(Y,X)
results = model.fit()
print(results.summary())
# グラフ生成
plt.plot(data["lnX"], data["lnY"], 'o', label="data")
plt.plot(data["lnX"], results.fittedvalues, label="OLS")
plt.xlim(min(data["lnX"])-0.5, max(data["lnX"])+0.5)
plt.ylim(min(data["lnY"])-0.5, max(data["lnY"])+0.5)
plt.title('Example6-3')
plt.legend(loc=2)
plt.show()
In [23]:
# BPテスト
BP = smsdia.het_breushpagan(results.resid, results.model.exog)
print('Breusch-Pagan test : ')
print('BP = ', BP[0])
print('p-value = ', BP[1])
あれ?まだ不均一分散残ってますね笑
ちなみに本書では何故か対数化する過程で「k0602.csv」の元のX,Yデータが変わってて対数化による不均一分散の解消が成功しているかのごとくなっています笑
「k0602.csv」と「k0603.csv」のデータ比較。
In [24]:
data6_2 = pd.read_csv('example/k0602.csv')
data6_3 = pd.read_csv('example/k0603.csv')
In [25]:
data6_2
Out[25]:
In [26]:
data6_3
Out[26]:
やっぱりX, Yの値が変わってる笑
とりあえず「k0603.csv」の場合の回帰も行います。
In [27]:
X = data6_3['lnX']
X = sm.add_constant(X)
Y = data6_3['lnY']
model = sm.OLS(Y,X)
results = model.fit()
print(results.summary())
plt.plot(data6_3["lnX"], data6_3["lnY"], 'o', label="data")
plt.plot(data6_3["lnX"], results.fittedvalues, label="OLS")
plt.xlim(min(data6_3["lnX"])-0.5, max(data6_3["lnX"])+0.5)
plt.ylim(min(data6_3["lnY"])-0.5, max(data6_3["lnY"])+0.5)
plt.title('Example6-3')
plt.legend(loc=2)
plt.show()
In [28]:
BP = smsdia.het_breushpagan(results.resid, results.model.exog)
print('Breusch-Pagan test : ')
print('BP = ', BP[0])
print('p-value = ', BP[1])
例題6-4で使う「k0604.csv」も「k0602.csv」とデータが異なるので、「k0602.csv」を基にしたデータの加工は省き、直接行います。
In [29]:
data = pd.read_csv('example/k0604.csv')
ちなみにデータの中身はこのようになっていて、
XZ = X / Z
YZ = Y / Z
で簡単に求めることが出来ます。
In [30]:
data
Out[30]:
In [31]:
X = data['XZ']
X = sm.add_constant(X)
Y = data['YZ']
model = sm.OLS(Y,X)
results = model.fit()
print(results.summary())
plt.plot(data["XZ"], data["YZ"], 'o', label="data")
plt.plot(data["XZ"], results.fittedvalues, label="OLS")
plt.xlim(min(data["XZ"])-0.1, max(data["XZ"])+0.1)
plt.ylim(min(data["YZ"])-0.1, max(data["YZ"])+0.1)
plt.title('Example6-4')
plt.legend(loc=2)
plt.show()
In [32]:
BP = smsdia.het_breushpagan(results.resid, results.model.exog)
print('Breusch-Pagan test : ')
print('BP = ', BP[0])
print('p-value = ', BP[1])