カテゴリーデータを説明変数に含む回帰分析
今度は説明変数にカテゴリーデータを含む場合の回帰分析を行う。
%matplotlib inline
対象となるデータはR処理系のcarパッケージに付属しているPrestigeというデータを write.csv(Prestige, "Prestige.csv", quote=FALSE, row.names=TRUE)
でCSVにしたものである。
このデータの各行は職業で、カナダの国勢調査で得られたデータである。変数は「定性的データ分析」(金明哲)によると次の通り。
education: 平均教育年数, income: 平均所得, women: 女性が占める割合, prestige: 職業地位の得点, census: カナダの国勢調査の職業コード, type: {bc: ブルーカラー, prof: 専門家, wc: ホワイトカラー}
職業コードは無視すると、typeがカテゴリーデータである。
次に散布図行列を書く。pandasのscatter_matrixは残念ながらカテゴリーデータを散布図行列に含めてくれない。もっとも含まれていても相関の解釈はしづらい。
from pandas.tools.plotting import scatter_matrix
scatter_matrix(prestige.drop("census", axis=1), figsize=(7, 7))
plt.show()
目的変数にしたいprestigeと相関を持ちそうなのがeducationとincomeであることがわかる。
重回帰分析にはstatsmodels.formula.apiのほうの関数を使う。というのもこちらを使うとカテゴリー変数に対して自動的にダミー変数を作ってくれるからだ。
import statsmodels.formula.api as smf
mod = smf.ols(formula="prestige ~ education + income + women + type", data=prestige)
res = mod.fit()
print res.summary()
次に変数選択を行う。ここではAICでもAdj. R-squaredでも同じく、education + income + typeの場合が最もよい。
formulas = [
"prestige ~ education + income",
"prestige ~ education + income + type",
"prestige ~ education + income + women + type",
]
steps = [[res.llf, res.aic, res.rsquared, res.rsquared_adj, formula]
for (res, formula) in [(smf.ols(formula=formula, data=prestige).fit(), formula) for formula in formulas]]
DataFrame(steps, columns=['Log-Likelihood', 'AIC', 'R-squared', 'Adj. R-squared', 'formula'])
選択された変数で改めて重回帰分析を行う。
mod = smf.ols(formula="prestige ~ education + income + type", data=prestige)
res = mod.fit()
print res.summary()
多重共線性について確かめるためVIFを計算する。
from statsmodels.stats.outliers_influence import variance_inflation_factor
num_cols = mod.exog.shape[1] # 説明変数の列数
vifs = [variance_inflation_factor(mod.exog, i)
for i in range(0, num_cols)]
DataFrame(vifs, index=mod.exog_names, columns=["VIF"])
ここではカテゴリー変数typeのダミー変数に対してVIFが計算されているが、 「定性的データ分析」のRの実行結果ではtypeそのものに対して6.102131という結果が出ている。 これをStatsmodelsでどうすればいいのか(Rがどう計算しているのか)はわからない。 いったん10以下であることから多重共線性はないと判断する。
「定性的データ分析」ではprestigeに対するincomeの関係が直線でなく右側が吊り上がっていることに注目し、変数incomeを対数変換することを提案している。 これをStatsmodelsで行う場合、式にはlog(income)でなく、numpy.logを使って書く必要があるようだ。
import math
mod = smf.ols(formula="prestige ~ education + np.log(income) + type", data=prestige)
res = mod.fit()
print res.summary()
AICが良くなり、Adj. R-squaredも0.828から0.849に向上している。