Skip to content

White 异方差检验

White 异方差检验(含平方项与交叉项)。

核心代码

py
    @staticmethod
    def white_test(
        df: pd.DataFrame,
        y_var: str,
        x_vars: List[str],
        decimals: int = 4
    ) -> Dict[str, Any]:
        """
        White检验:检验异方差性(包含交叉项和平方项)

        参数:
            df: 数据框
            y_var: 因变量名
            x_vars: 自变量列表
            decimals: 小数位数

        返回:
            包含检验结果的字典
        """
        # 准备数据
        cols = [y_var] + x_vars
        df_clean = df[cols].dropna()

        # 1. 估计OLS模型
        formula = build_patsy_formula(y_var, x_vars)
        model = smf.ols(formula, data=df_clean)
        result = model.fit()

        # 2. 获取残差
        residuals = result.resid

        # 3. 计算残差平方
        resid_squared = residuals ** 2

        # 4. 构造辅助回归的自变量(包含原变量、平方项和交叉项)
        df_aux = df_clean[x_vars].copy()

        # 添加平方项
        for var in x_vars:
            df_aux[f'{var}_sq'] = df_clean[var] ** 2

        # 添加交叉项
        for i, var1 in enumerate(x_vars):
            for var2 in x_vars[i+1:]:
                df_aux[f'{var1}_{var2}'] = df_clean[var1] * df_clean[var2]

        # 5. 用残差平方对扩展的自变量回归
        df_aux['resid_sq'] = resid_squared

        aux_vars = [col for col in df_aux.columns if col != 'resid_sq']

        # 检查样本量是否足够
        if len(df_clean) < len(aux_vars) + 2:
            # 如果样本量不足,只使用原变量和平方项(不包含交叉项)
            df_aux_simple = df_clean[x_vars].copy()
            for var in x_vars:
                df_aux_simple[f'{var}_sq'] = df_clean[var] ** 2
            df_aux_simple['resid_sq'] = resid_squared
            aux_vars = [col for col in df_aux_simple.columns if col != 'resid_sq']

            aux_formula = build_patsy_formula('resid_sq', aux_vars)
            aux_model = smf.ols(aux_formula, data=df_aux_simple)
        else:
            aux_formula = build_patsy_formula('resid_sq', aux_vars)
            aux_model = smf.ols(aux_formula, data=df_aux)

        aux_result = aux_model.fit()

        # 6. 计算LM统计量 = n * R²
        n = len(df_clean)
        r_squared = aux_result.rsquared
        lm_stat = n * r_squared

        # 7. 自由度 = 辅助回归中的自变量个数
        df_test = len(aux_vars)

        # 8. 计算p值(卡方分布)
        p_value = 1 - chi2.cdf(lm_stat, df_test)

        # 9. 判断结果
        if p_value < 0.01:
            conclusion = _('强烈拒绝原假设,存在显著异方差')
            stars = "***"
        elif p_value < 0.05:
            conclusion = _('拒绝原假设,存在异方差')
            stars = "**"
        elif p_value < 0.1:
            conclusion = _('弱拒绝原假设,可能存在异方差')
            stars = "*"
        else:
            conclusion = _('不能拒绝原假设,不存在显著异方差')
            stars = ""

        return {
            'test_name': 'White Test for Heteroskedasticity',
            'null_hypothesis': _('误差项具有同方差性(不存在异方差)'),
            'alternative_hypothesis': _('误差项具有异方差性'),
            'lm_statistic': round(lm_stat, decimals),
            'chi2_statistic': round(lm_stat, decimals),
            'df': df_test,
            'p_value': round(p_value, decimals),
            'significance': stars,
            'conclusion': conclusion,
            'n_obs': n,
            'aux_r_squared': round(r_squared, decimals),
            'n_aux_vars': df_test
        }

Released under the AGPL-3.0 License.