Skip to content

Logit 模型

Logit 二元选择模型,支持高维固定效应。

核心代码

py
    def _fit_discrete_with_fe(
        self,
        df: pd.DataFrame,
        entity_col: str,
        time_col: str
    ) -> Any:
        """
        执行带固定效应的Logit/Probit回归

        使用虚拟变量方法实现固定效应

        参数:
            df: 清洗后的数据框
            entity_col: 个体标识列
            time_col: 时间标识列

        返回:
            statsmodels 拟合结果

        注意:
            - 固定效应Logit/Probit存在附带参数问题(incidental parameters problem)
            - 当面板时间维度较短(T<10)时,估计可能有偏
        """
        df, effect_aliases, notes = self._prepare_discrete_fe_dimensions(df)
        self._emit_preparation_notes(notes)

        # 1. 检查面板结构并给出警告
        if entity_col and time_col:
            panel_structure = df.groupby(entity_col)[time_col].nunique()
            avg_T = panel_structure.mean()
            if avg_T < 10:
                warnings.warn(
                    _('警告: 平均时间维度T=%(avg_t)s < 10,固定效应%(method)s模型可能存在附带参数偏误。') % {'avg_t': format(avg_T, '.1f'), 'method': self.method}
                    + _('建议使用线性概率模型(OLS with FE)或增加时间维度。'),
                    UserWarning
                )

        # 2. 预处理:移除完全分离的固定效应组
        # 对于每个固定效应维度,移除Y值完全相同的组
        for fe_var in self.fe_vars:
            fe_alias = effect_aliases.get(fe_var)
            if fe_alias and fe_alias in df.columns:
                # 计算每组的Y值方差
                group_var = df.groupby(fe_alias)[self.y_var].agg(['std', 'count'])
                # 移除方差为0(完全分离)或样本量<2的组
                valid_groups = group_var[(group_var['std'] > 0) & (group_var['count'] >= 2)].index
                original_n = len(df)
                df = df[df[fe_alias].isin(valid_groups)]
                removed_n = original_n - len(df)
                if removed_n > 0:
                    warnings.warn(
                        _('警告: 移除了%(removed_n)s个观测(%(fe_var)s组内Y值完全相同或样本量不足)。') % {'removed_n': removed_n, 'fe_var': fe_var},
                        UserWarning
                    )

        # 检查剩余样本量
        if len(df) < 50:
            raise ValueError(_('数据预处理后样本量过小(%(n)s),无法拟合固定效应模型。') % {'n': len(df)})
        try:
            return self._fit_absorbed_discrete_model(df, effect_aliases)
        except np.linalg.LinAlgError:
            raise ValueError(
                _('模型拟合失败(高维固定效应离散模型数值不稳定)。可能原因:\n')
                + _('1. 固定效应维度过多(当前:%(vars)s\n') % {'vars': ', '.join(self.fe_vars)}
                + _('2. 存在完全或近似完全分离\n')
                + _('3. 解释变量在固定效应内几乎没有有效变异\n')
                + _('建议:检查因变量组内变异、缩放连续变量,或减少共线变量。')
            )
        except Exception as e:
            raise ValueError(_('模型拟合失败: %(error)s') % {'error': str(e)})

Released under the AGPL-3.0 License.