LoginSignup
1
1

More than 1 year has passed since last update.

重回帰分析にダミー変数を使うとき

Posted at

重回帰分析にダミー変数を使うとき

1. 重回帰分析に使用するデータ

import pandas as pd

df5 = pd.DataFrame({
  'x1': [2, 2, 3, 1, 2, 3, 2, 2, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1],
  'x2': [2, 2, 3, 2, 2, 1, 2, 3, 2, 3, 2, 1, 3, 2, 2, 1, 1, 3, 2, 1],
   'y': [17, 20, 24, 15, 20, 19, 20, 22, 20, 26, 24, 14, 22, 23, 23, 19, 13, 27, 17, 13]})

前の記事では $x_1$, $x_2$ ともに連続変数として,そのまま説明変数として使った。

今回,$x_2$ をカテゴリー変数として扱うことにする。

pd.get_dummies() により,$k$ 個のカテゴリーを表すために 冗長ではあるが $k$ 個のダミー変数を作る。

$k$ 個のダミー変数は一次従属なので,正規方程式の逆行列を求めて...というような昔ながらのアルゴリズムを使うと,Singular matrix errorが発生し,解を求めることができない。

ちゃんとしたアルゴリズムであれば,$k$ 個のダミー変数を使うようにしても,解は求まる。

しかし,$k$ 個のダミー変数を使った場合と $k-1$ 個のダミー変数を使った場合でどのような違いがあるのか,そもそも違いなんてないのか?

実際に見てみようじゃないかというのが今回のテーマ。

重回帰分析でカテゴリー変数を使用する場合には,どれか 1 つのダミー変数を削除して,$k-1$ 個のダミー変数を使用すればよい。あるいは pd.get_dummies()drop_first=True 引数で最初のダミー変数を除くこともできる。

dummy3 = pd.get_dummies(df5["x2"], prefix="d")
print(dummy3.head(3))
   d_1  d_2  d_3
0    0    1    0
1    0    1    0
2    0    0    1
dummy2 = pd.get_dummies(df5["x2"], prefix="d", drop_first=True)
print(dummy2.head(3))
   d_2  d_3
0    1    0
1    1    0
2    0    1

実際に使用する変数は後で決めることにして,以下のようなデータフレームを作る。

df6 = pd.concat([df5, dummy3], axis=1)
print(df6.head(5))
   x1  x2   y  d_1  d_2  d_3
0   2   2  17    0    1    0
1   2   2  20    0    1    0
2   3   3  24    0    0    1
3   1   2  15    0    1    0
4   2   2  20    0    1    0

2. sklern.linear_model.LinearRegression による分析

2.1. 3 個のダミー変数を使う場合

連続変数 $x1$,ダミー変数 $d_1$,$d_2$,$d_3$ を説明変数として,$y$ を予測する重回帰式を求める。

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
X = df6.drop(['x2', 'y'], axis=1)
print(X.head(3))
   x1  d_1  d_2  d_3
0   2    0    1    0
1   2    0    1    0
2   3    0    0    1
y = df6['y']

以前に作っておいた関数を使って結果を求める。

from sklearn.linear_model import LinearRegression
import pandas as pd

def lm(X, y):
    lr = LinearRegression()
    lr = lr.fit(X, y)
    b0, b = lr.intercept_, lr.coef_
    beta = tuple(b * X.std(axis=0) / y.std())
    R2 = lr.score(X, y)
    yhat = lr.predict(X)
    Se = sum((y - yhat)**2)
    St = sum((y - y.mean())**2)
    R2adj = 1 - (Se / (n - p - 1)) / (St / (n - 1))
    return(dict(b0=b0, b=b, beta=beta, R2=R2, yhat=yhat, R2adj=R2adj))
X = df6.drop(['x2', 'y'], axis=1)
y = df6['y']
lm(X, y)
{'b0': 14.509019607843138,
 'b': array([ 2.74117647, -3.84313725,  0.1827451 ,  3.66039216]),
 'beta': (0.4571465989589744,
  -0.4148666354410395,
  0.022779160706274896,
  0.3951393035925156),
 'R2': 0.773055971922641,
 'yhat': array([20.17411765, 20.17411765, 26.39294118, 17.43294118, 20.17411765,
        18.88941176, 20.17411765, 23.65176471, 20.17411765, 26.39294118,
        20.17411765, 16.14823529, 20.91058824, 22.91529412, 20.17411765,
        16.14823529, 13.40705882, 23.65176471, 17.43294118, 13.40705882]),
 'R2adj': 0.7125375644353453}

予測式は以下のようになる。

$\hat{y} = b_0 + b_1\ x_1 + b_2\ d_1 + b_3\ d_2 + b_4\ d_3 \tag{1}$

$\hat{y} = 14.509019607843138 + 2.74117647\ x_1 -3.84313725\ d_1 + 0.1827451\ d_2 + 3.66039216\ d_3 \tag{2}$

2.2. 2 個のダミー変数を使う場合

X = df6.drop(['x2', 'y', 'd3_1'], axis=1)
y = df6['y']
results = lm(X, y)
results
{'b0': 10.665882352941175,
 'b': array([2.74117647, 4.02588235, 7.50352941]),
 'beta': (0.45714659895897425, 0.501825888005632, 0.8100059390335557),
 'R2': 0.7730559719226411,
 'yhat': array([20.17411765, 20.17411765, 26.39294118, 17.43294118, 20.17411765,
        18.88941176, 20.17411765, 23.65176471, 20.17411765, 26.39294118,
        20.17411765, 16.14823529, 20.91058824, 22.91529412, 20.17411765,
        16.14823529, 13.40705882, 23.65176471, 17.43294118, 13.40705882]),
 'R2adj': 0.7125375644353453}

予測値 yhat を見れば判るように,ダミー変数が 3 個の場合も 2 個の場合も同じ予測値になっている。

次式に示すように,$k$ 個のカテゴリーに対する $k$ 個のダミー変数に対する係数は,一次従属なので定数項とのやり取りでどのようにでもなる。例えば,(1) 式と (3) 式は同じになる。

逆にいえば,回帰式を一意的にするには $k-1$ 個のダミー変数を使うようにすれば良い。最も,どのダミー変数を除くかで一意的にはなりえないのではあるが。

$\hat{y} = b_0 + b_1\ x_1 + 0\ d_1 + b_3\ d_2 + b_4\ d_3 \tag{3}$

$\hat{y} = 10.665882352941175 + 2.74117647\ x_1 + 0\ d_1 + 4.02588235\ d_2 + 7.50352941\ d_3 \tag{4}$

$\hat{y} = (10.665882352941175 + 3.84313725) + 2.74117647\ x_1 + (0 - 3.84313725)\ d_1 + (4.02588235 - 3.84313725)\ d_2 + (7.50352941 - 3.84313725)\ d_3 \tag{5}$

$\hat{y} = 14.509019602941175 + 2.74117647\ x_1 - 3.84313725\ d_1 + 0.1827451\ d_2 + 3.66039216\ d_3 \tag{6}$

3. statsmodels.formula.api を用いて重回帰分析を行う

3.1. 3 個のダミー変数を使う場合

import pandas as pd
import statsmodels.formula.api as smf

model = smf.ols(formula='y ~ x1 + d_1 + d_2 + d_3', data=df6)
fitted3 = model.fit();
print(fitted3.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       0.773
Model:                            OLS   Adj. R-squared:                  0.731
Method:                 Least Squares   F-statistic:                     18.17
Date:                Wed, 18 May 2022   Prob (F-statistic):           2.10e-05
Time:                        16:44:53   Log-Likelihood:                -41.330
No. Observations:                  20   AIC:                             90.66
Df Residuals:                      16   BIC:                             94.64
Df Model:                           3                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept     10.8818      1.145      9.504      0.000       8.455      13.309
x1             2.7412      0.733      3.741      0.002       1.188       4.295
d_1           -0.2159      0.810     -0.267      0.793      -1.933       1.501
d_2            3.8100      0.684      5.570      0.000       2.360       5.260
d_3            7.2876      0.939      7.763      0.000       5.297       9.278
==============================================================================
Omnibus:                        1.082   Durbin-Watson:                   1.850
Prob(Omnibus):                  0.582   Jarque-Bera (JB):                0.941
Skew:                           0.471   Prob(JB):                        0.625
Kurtosis:                       2.510   Cond. No.                     1.53e+16
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The smallest eigenvalue is 4.72e-31. This might indicate that there are
strong multicollinearity problems or that the design matrix is singular.

$d_1$ の $p$ 値が 0.793 となっており, $d_1$ は使う必要がないことを示唆している。

3.2. 2 個のダミー変数を使う場合

model = smf.ols(formula='y ~ x1 + d_2 + d_3', data=df6)
fitted2 = model.fit();
print(fitted2.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       0.773
Model:                            OLS   Adj. R-squared:                  0.731
Method:                 Least Squares   F-statistic:                     18.17
Date:                Wed, 18 May 2022   Prob (F-statistic):           2.10e-05
Time:                        16:45:50   Log-Likelihood:                -41.330
No. Observations:                  20   AIC:                             90.66
Df Residuals:                      16   BIC:                             94.64
Df Model:                           3                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept     10.6659      1.629      6.549      0.000       7.213      14.119
x1             2.7412      0.733      3.741      0.002       1.188       4.295
d_2            4.0259      1.172      3.434      0.003       1.540       6.511
d_3            7.5035      1.383      5.427      0.000       4.572      10.435
==============================================================================
Omnibus:                        1.082   Durbin-Watson:                   1.850
Prob(Omnibus):                  0.582   Jarque-Bera (JB):                0.941
Skew:                           0.471   Prob(JB):                        0.625
Kurtosis:                       2.510   Cond. No.                         9.39
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

この場合も前節と同じく,3 個のダミー変数を使った重回帰分析の結果から,どれか一つのダミー変数を除いた結果を導くことができる。

(10.8818 - 0.2159, -0.2159 + 0.2159, 3.8100 + 0.2159, 7.2876 + 0.2159)
(10.6659, 0.0, 4.0259, 7.503500000000001)

当たり前であるが,$k$個のダミー変数を使おうが,どのダミー変数を除こうが($k−1$個のダミー変数を使う),予測結果は変わらない。

print(fitted3.predict())
[20.17411765 20.17411765 26.39294118 17.43294118 20.17411765 18.88941176
 20.17411765 23.65176471 20.17411765 26.39294118 20.17411765 16.14823529
 20.91058824 22.91529412 20.17411765 16.14823529 13.40705882 23.65176471
 17.43294118 13.40705882]
print(fitted2.predict())
[20.17411765 20.17411765 26.39294118 17.43294118 20.17411765 18.88941176
 20.17411765 23.65176471 20.17411765 26.39294118 20.17411765 16.14823529
 20.91058824 22.91529412 20.17411765 16.14823529 13.40705882 23.65176471
 17.43294118 13.40705882]

4. 結論

説明変数にカテゴリー変数を使う場合には,「カテゴリー数」個のダミー変数を使うよりは,「カテゴリー数 - 1」個のダミー変数を使うほうがよい。

R の lm() 関数では自動的に一次従属な説明変数はモデルから外される。

1
1
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
1
1