<jupyter_start><jupyter_text>Panel Data Models---<jupyter_code>import pandas as pd
import numpy as np

import statsmodels.api as sm

from linearmodels import PooledOLS
from linearmodels import RandomEffects
from linearmodels import PanelOLS
from linearmodels import FirstDifferenceOLS

from stargazer.stargazer import Stargazer
# Import crime data from North Carolina between 1981 to 1987
data = pd.read_csv("data/crime.csv", index_col=0)
data
# Best practice: check dtypes
# There are two columns with object dtypes that should be further investigated
# BUT since we will not be using those columns in this notebook, 
# we can safely ignore them 

data.dtypes
data.columns<jupyter_output><empty_output><jupyter_text>1. Random Effects, Fixed Effects, and First Differences---  Comments:- In notebook 1_introduction, I wrote the code for both non-formula and formula APIs to running regressions in statsmodels.- However, for simplicity and comparability with R code, I will only use the formula API from this notebook onwards.- The main library from this notebook onwards is linearmodels.- Linearmodels is a library that extends statsmodels with econometric models.<jupyter_code># Important! You must set a multi-index (entity, time) for panel data methods in linearmodels to work

data = data.set_index(['county','year'])
data<jupyter_output><empty_output><jupyter_text>1.1. Pooled OLS<jupyter_code># Naive OLS assuming i.i.d. data

mod_OLS = PooledOLS.from_formula("crmrte ~ 1 + density + taxpc + wcon + pctmin", data=data)
res_OLS = mod_OLS.fit()
res_OLS.summary<jupyter_output><empty_output><jupyter_text>1.2. Random Effects<jupyter_code>mod_randeff = RandomEffects.from_formula("crmrte ~ 1 + density + taxpc + wcon + pctmin", data=data)
res_randeff = mod_randeff.fit()
res_randeff.summary<jupyter_output><empty_output><jupyter_text>1.3. Fixed Effects<jupyter_code># Entity fixed effects

entity_fe_formula = "crmrte ~ density + taxpc + wcon + pctmin + EntityEffects"
mod_entity_fe = PanelOLS.from_formula(entity_fe_formula, data=data, drop_absorbed=True)
res_entity_fe = mod_entity_fe.fit()
res_entity_fe.summary
# Entity and time period fixed effects

twoways_fe_formula = "crmrte ~ density + taxpc + wcon + pctmin + TimeEffects + EntityEffects"
mod_twoways_fe = PanelOLS.from_formula(twoways_fe_formula, data=data, drop_absorbed=True)
res_twoways_fe = mod_twoways_fe.fit()
res_twoways_fe.summary<jupyter_output><empty_output><jupyter_text>1.4. First Differences<jupyter_code>mod_fd = FirstDifferenceOLS.from_formula("crmrte ~ density + taxpc + wcon", data=data)
res_fd = mod_fd.fit()
res_fd.summary<jupyter_output><empty_output><jupyter_text>2. Standard Errors---  Note:- Three covariance estiminators are supported in linearmodels:    1. White's (1980) robust standard errors    2. Clustered standard errors (entity, time, two-way)    3. Driscoll-Kraay HAC standard errors    Reference: https://bashtage.github.io/linearmodels/doc/panel/models.html<jupyter_code># warning: this is probably bad
# White's (1980) robust standard errors

res_entity_fe_robust = mod_entity_fe.fit(cov_type="robust")
res_entity_fe_robust.summary
# Clustered by entity (fixed effects)

res_fe_clustered_entity = mod_entity_fe.fit(cov_type="clustered", cluster_entity=True)
res_fe_clustered_entity.summary
# Clustered by entity (first difference)

res_fd_clustered_entity = mod_fd.fit(cov_type="clustered", cluster_entity=True)
res_fd_clustered_entity.summary
# Clustered by time (fixed effects)

res_fe_clustered_time = mod_entity_fe.fit(cov_type="clustered", cluster_time=True)
res_fe_clustered_time.summary
# Clustered by time (first difference)

res_fd_clustered_time = mod_fd.fit(cov_type="clustered", cluster_time=True)
res_fd_clustered_time.summary
# Newey-West
# WARNING: linearmodels currently does not implement Newey-West SEs
# But statsmodels does! 
# The following code implements a entity-dummies fixed effects regression
# Note: you must include "-1" into the formula to remove the intercept

data_noindex = data.reset_index()
mod_fe_NW = sm.formula.ols("crmrte ~ density + taxpc + wcon + C(county) -1", data=data_noindex)
res_fe_NW = mod_fe_NW.fit(cov_type="HAC", cov_kwds={"maxlags":1})
res_fe_NW.summary()
# Driscoll-Kraay HAC

res_fe_HAC = mod_entity_fe.fit(cov_type="kernel", kernel="andrews")
res_fe_HAC.summary<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08929804372842348, 'fraction_numerical': 0.008285385500575374, 'mean_word_length': 6.611208406304729, 'pattern_counts': {'":': 1, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '64592', 'license': 'MIT', 'n_tokens_mistral': 1527, 'n_tokens_neox': 1480, 'n_words': 378, 'path': 'notebooks/2_panel.ipynb', 'repo_name': 'topher-lo/PyEC333', 'size': '4345'}