外观
F 检验
固定效应与混合 OLS 的模型选择 F 检验。
核心代码
py
@staticmethod
def f_test_fe_vs_pooled(
df: pd.DataFrame,
y_var: str,
x_vars: List[str],
entity_col: str,
time_col: str,
decimals: int = 4
) -> Dict[str, Any]:
"""
F检验:固定效应模型 vs 混合OLS模型
参数:
df: 数据框
y_var: 因变量名
x_vars: 自变量列表
entity_col: 个体标识列
time_col: 时间标识列
decimals: 小数位数
返回:
包含检验结果的字典
"""
# 准备数据
cols = [y_var] + x_vars + [entity_col, time_col]
df_clean = df[cols].dropna()
df_clean, entity_alias, time_alias = ModelTests._prepare_panel_test_df(
df_clean,
entity_col,
time_col
)
df_clean = drop_singletons_func(df_clean, entity_alias)
# 1. 估计混合OLS模型
formula = build_patsy_formula(y_var, x_vars)
pooled_model = smf.ols(formula, data=df_clean)
pooled_result = pooled_model.fit()
rss_pooled = pooled_result.ssr # 残差平方和
# 2. 估计固定效应模型
df_panel = df_clean.set_index([entity_alias, time_alias])
y = df_panel[y_var]
x = df_panel[x_vars]
fe_model = PanelOLS(y, x, entity_effects=True, drop_absorbed=True)
fe_result = fe_model.fit()
rss_fe = fe_result.resid_ss # 残差平方和
# 3. 计算F统计量
# F = [(RSS_pooled - RSS_fe) / (N-1)] / [RSS_fe / (NT - N - K)]
n_entities = df_clean[entity_alias].nunique()
n_obs = len(df_clean)
k_vars = len(x_vars)
df1 = n_entities - 1 # 分子自由度
df2 = n_obs - n_entities - k_vars # 分母自由度
f_stat = ((rss_pooled - rss_fe) / df1) / (rss_fe / df2)
p_value = 1 - f_dist.cdf(f_stat, df1, df2)
# 4. 判断结果
if p_value < 0.01:
conclusion = _('强烈拒绝原假设,应使用固定效应模型')
stars = "***"
elif p_value < 0.05:
conclusion = _('拒绝原假设,应使用固定效应模型')
stars = "**"
elif p_value < 0.1:
conclusion = _('弱拒绝原假设,倾向使用固定效应模型')
stars = "*"
else:
conclusion = _('不能拒绝原假设,可使用混合OLS模型')
stars = ""
return {
'test_name': 'F Test (Fixed Effects vs Pooled OLS)',
'null_hypothesis': _('所有个体效应为0(混合OLS模型合适)'),
'alternative_hypothesis': _('至少存在一个个体效应不为0(固定效应模型合适)'),
'f_statistic': round(f_stat, decimals),
'df1': df1,
'df2': df2,
'p_value': round(p_value, decimals),
'significance': stars,
'conclusion': conclusion,
'rss_pooled': round(rss_pooled, decimals),
'rss_fe': round(rss_fe, decimals),
'n_entities': n_entities,
'n_obs': n_obs
}