Skip to content

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
        }

Released under the AGPL-3.0 License.