外观
Probit 模型
Probit 二元选择模型,支持高维固定效应。
核心代码
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)})