Panel 회귀모형

2020. 10. 24. 23:41계량경제학

반응형

Panel 회귀모형을 활용하면, 이전 포스팅에서 언급했던 Omitted variable과 같은 이슈를 일부 해소할 수 있습니다. 만약 Omitted variable이 있고 해당 Omitted variable이 무엇인지 정확히 알기 어려울 때, Panel 회귀모형을 활용하면 시간 또는 그룹차원에서 Parameter 추정에 왜곡을 주는 요소를 회귀분석에 포함하여 분석할 수 있습니다.

먼저 Panel 데이터는 $n$개의 entities로만 구성되어 있는 Cross-section 데이터와 다르게, $n$개의 entities와 시간 T로 구성되어 있습니다.

$$(X_{it}, Y_{it}),  i=1,\cdots ,n \,\,and\,\, t =1,\cdots,T $$

예시를 통해, Panel 데이터 및 상이한 시간대에 따른 회귀분석의 Parameter가 어떻게 변하는지 알아보겠습니다.

## Data load
Fatalities = pd.read_csv("Fatalities.csv")
Fatalities.info()

Fatalities["fatal_rate"] = (Fatalities["fatal"] / Fatalities["pop"]) * 10000

Fatal_1982 = Fatalities.loc[Fatalities["year"]==1982]
Fatal_1988 = Fatalities.loc[Fatalities["year"]==1988]

## simple regression model
fatal_1982_mod = smf.ols("fatal_rate~beertax", data=Fatal_1982).fit()
fatal_1982_mod.summary()

'''
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept      2.0104      0.139     14.455      0.000       1.730       2.290
beertax        0.1485      0.188      0.788      0.435      -0.231       0.528
==============================================================================
'''

fatal_1988_mod = smf.ols("fatal_rate~beertax", data=Fatal_1988).fit()
fatal_1988_mod.summary()

'''
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept      1.8591      0.106     17.540      0.000       1.646       2.072
beertax        0.4388      0.164      2.668      0.011       0.108       0.770
==============================================================================
'''


sns.regplot(x="beertax",  y="fatal_rate", data=Fatal_1982)
plt.title("Traffic Fatality Rates and Beer Taxes in 1982")

sns.regplot(x="beertax",  y="fatal_rate", data=Fatal_1988, color="orange")
plt.title("Traffic Fatality Rates and Beer Taxes in 1988")

추정된 계수를 보면, 1988년의 데이터를 활용한 Parameter값이 1982년의 데이터를 활용한 Parameter값보다 거의 3배가 큰 것을 확인할 수 있습니다. 이와 같이 시간대를 활용하면 기존 Cross-section에서 잡아내지 못하는 효과를 분석해볼 수 있습니다. 

[Fixed effect 회귀분석]

앞서 말한것과 같이 Panel 회귀모형은 연구자가 관찰하기 어려운 요인들을 통제하여 또는 포함하여 분석하는 방법인다. Fixed effect 회귀분석은 One-way Fixed 모델과 Two-way Fixed 모델로 나눠질 수 있는데 One-way Fixed 모델은 time-invariant한 각 Entity가지는 특성을 포함하는 것이고, Two-way Fixed 모델은 각 Entity가 가지는 특성 및 시간에 따라 변화하는 요인까지 포함한 모델입니다.

아래와 같은 회귀분석 모형을 고려해보겠습니다.

$$ Y_{it} = \beta_0 + \beta_1 X_{it} + \beta_2 Z_i +\mu_{it} $$

이 때 $Z_i$은 time-invariant한 관찰되지 않은 요인을 나타냅니다. $\alpha_i = \beta_0 +\beta_2 Z_i$ 라고 한다면 위의 식은 다시 아래와 같이 표현될 수 있습니다.

또한 위의 식은 Dummy 회귀분석으로 표현할 수 있습니다.

그런데 위와 같이 모든 Dummy variable을 활용하여 우리가 관심있는 $\beta_1$을 추정하는 것은 비효율적이기 때문에 "entity-demeaned" 방법을 활용하여 계수를 추정하게 됩니다.

최종적으로 아래와 같이 정리될 수 있습니다.

이제 Dummy 회귀분석과 entity-demeaned 방법을 활용한 회귀분석을 통해서 계수를 비교해보도록 하겠습니다.

## dummy regression
fatal_fe_lm_mod = smf.ols("fatal_rate~beertax+state-1", data=Fatalities).fit()
fatal_fe_lm_mod.summary()

##  entity-demeaned
Fatalities_demeaned = pd.DataFrame()
Fatalities_demeaned["fatal_rate"] = Fatalities["fatal_rate"]-Fatalities.groupby("state")["fatal_rate"].transform("mean")
Fatalities_demeaned["beertax"] = Fatalities["beertax"]-Fatalities.groupby("state")["beertax"].transform("mean")
smf.ols("fatal_rate~ beertax -1", data=Fatalities_demeaned).fit().summary()

'''
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
state[al]      3.4776      0.313     11.098      0.000       2.861       4.094
state[ar]      2.8227      0.132     21.364      0.000       2.563       3.083
state[az]      2.9099      0.093     31.445      0.000       2.728       3.092
state[ca]      1.9682      0.074     26.594      0.000       1.822       2.114
state[co]      1.9933      0.080     24.802      0.000       1.835       2.152
state[ct]      1.6154      0.084     19.251      0.000       1.450       1.781
state[de]      2.1700      0.077     28.016      0.000       2.018       2.322
state[fl]      3.2095      0.222     14.489      0.000       2.774       3.645
state[ga]      4.0022      0.464      8.625      0.000       3.089       4.916
state[ia]      1.9337      0.102     18.918      0.000       1.733       2.135
state[id]      2.8086      0.099     28.437      0.000       2.614       3.003
state[il]      1.5160      0.078     19.318      0.000       1.362       1.670
state[in]      2.0161      0.089     22.736      0.000       1.842       2.191
state[ks]      2.2544      0.109     20.753      0.000       2.041       2.468
state[ky]      2.2601      0.080     28.089      0.000       2.102       2.418
state[la]      2.6305      0.163     16.171      0.000       2.310       2.951
state[ma]      1.3679      0.086     15.818      0.000       1.198       1.538
state[md]      1.7712      0.082     21.480      0.000       1.609       1.933
state[me]      2.3697      0.160     14.805      0.000       2.055       2.685
state[mi]      1.9931      0.117     17.089      0.000       1.764       2.223
state[mn]      1.5804      0.094     16.880      0.000       1.396       1.765
state[mo]      2.1814      0.093     23.576      0.000       1.999       2.363
state[ms]      3.4486      0.209     16.472      0.000       3.036       3.861
state[mt]      3.1172      0.094     33.017      0.000       2.931       3.303
state[nc]      3.1872      0.252     12.661      0.000       2.692       3.683
state[nd]      1.8542      0.102     18.191      0.000       1.654       2.055
state[ne]      1.9555      0.106     18.534      0.000       1.748       2.163
state[nh]      2.2232      0.141     15.751      0.000       1.945       2.501
state[nj]      1.3719      0.073     18.709      0.000       1.228       1.516
state[nm]      3.9040      0.102     38.449      0.000       3.704       4.104
state[nv]      2.8769      0.081     35.492      0.000       2.717       3.036
state[ny]      1.2910      0.076     17.070      0.000       1.142       1.440
state[oh]      1.8032      0.102     17.691      0.000       1.603       2.004
state[ok]      2.9326      0.184     15.913      0.000       2.570       3.295
state[or]      2.3096      0.081     28.453      0.000       2.150       2.469
state[pa]      1.7102      0.086     19.776      0.000       1.540       1.880
state[ri]      1.2126      0.078     15.640      0.000       1.060       1.365
state[sc]      4.0348      0.355     11.372      0.000       3.336       4.733
state[sd]      2.4739      0.141     17.519      0.000       2.196       2.752
state[tn]      2.6020      0.092     28.398      0.000       2.422       2.782
state[tx]      2.5602      0.109     23.589      0.000       2.347       2.774
state[ut]      2.3137      0.155     14.972      0.000       2.010       2.618
state[va]      2.1874      0.147     14.917      0.000       1.899       2.476
state[vt]      2.5116      0.140     17.975      0.000       2.237       2.787
state[wa]      1.8181      0.082     22.084      0.000       1.656       1.980
state[wi]      1.7184      0.077     22.185      0.000       1.566       1.871
state[wv]      2.5809      0.108     23.971      0.000       2.369       2.793
state[wy]      3.2491      0.072     44.922      0.000       3.107       3.391
beertax       -0.6559      0.188     -3.491      0.001      -1.026      -0.286
==============================================================================
'''
##  entity-demeaned
Fatalities_demeaned = pd.DataFrame()
Fatalities_demeaned["fatal_rate"] = Fatalities["fatal_rate"]-Fatalities.groupby("state")["fatal_rate"].transform("mean")
Fatalities_demeaned["beertax"] = Fatalities["beertax"]-Fatalities.groupby("state")["beertax"].transform("mean")
smf.ols("fatal_rate~ beertax -1", data=Fatalities_demeaned).fit().summary()

'''
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
beertax       -0.6559      0.174     -3.772      0.000      -0.998      -0.314
==============================================================================
'''

위의 결과를 보면 추정된 계수(beertax)와 통계적 유의성이 동일함을 확인할 수 있습니다. t-statistic수치가 조금 상이하지만, 이것은 데이터를 처리하는 과정에서 발생한 것으로 볼 수 있을 정도로 미미합니다.

이번에는 Python에서 제공하는 Linearmodels 패키지를 활용하여 추정해보도록 하겠습니다.

from linearmodels import PanelOLS


## one-way fixed model

new_Fatalities = Fatalities.copy()
new_Fatalities=new_Fatalities.set_index(["state","year"])
mod = PanelOLS.from_formula('fatal_rate ~ beertax + EntityEffects', new_Fatalities )
res =mod.fit(cov_type = "clustered", cluster_entity=True)
print(res)

'''
==============================================================================
            Parameter  Std. Err.     T-stat    P-value    Lower CI    Upper CI
------------------------------------------------------------------------------
beertax       -0.6559     0.2888    -2.2710     0.0239     -1.2243     -0.0874
==============================================================================
'''

## two-way fixed model

mod = PanelOLS.from_formula('fatal_rate ~ beertax + EntityEffects+TimeEffects', new_Fatalities )
res =mod.fit(cov_type = "clustered", cluster_entity=True, clsuter_time =True)
print(res)

'''
==============================================================================
            Parameter  Std. Err.     T-stat    P-value    Lower CI    Upper CI
------------------------------------------------------------------------------
beertax       -0.6400     0.3823    -1.6740     0.0953     -1.3925      0.1126
==============================================================================
'''

PanelOLS 패키지를 이용할 때 cov_type = "clustered"로 주로 활용합니다. 이는 아래와 같이 그룹이 상이할 때 오차의 평균이 0이 아님을 가정하고 계수를 추정하는 것입니다.

http://econweb.umd.edu/~sarzosa/teach/2/Disc2_Cluster_handout.pdf

 

반응형