回归中‘Coefficients: not defined because of singularities’错误解决方法
回归模型奇点问题解决建议
你当前的回归报错核心原因有两个:
- 数据类型错误:所有数值列被存为字符型,
dynlm自动将其处理为因子变量,生成了大量虚拟变量(比如Jan14就衍生出3个虚拟变量),直接导致自变量维度远超观测数。 - 自由度严重不足:仅4个观测值,却加入了24个月度变量+多个其他自变量,完全没有剩余自由度估计残差,出现完美拟合(残差全为0)和奇点问题。
一、先修复数据类型
首先把所有数值列转换为数值型,避免因子变量爆炸:
# 除Office列外,其余列转为数值类型 D[, -1] <- lapply(D[, -1], as.numeric)
二、精简自变量,解决自由度不足
4个观测最多只能估计3个非截距项系数(自由度=观测数-自变量数-1),必须大幅精简变量:
- 合并月度变量:将2014、2015年的月度数据求和/取平均,生成年度总变量,或合并为季度变量,减少自变量数量。
- 规避虚拟变量陷阱:
urad_1-urad_4是互斥分组虚拟变量,只需保留3个(比如去掉urad_1),避免完全共线性。 - 筛选核心变量:优先保留对
entries17解释力强的变量(比如entries16,年度数据相关性更高),去掉冗余月度变量。
示例简化模型:
# 生成2014、2015年度总变量替代月度变量 D$total_2014 <- rowSums(D[, paste0(c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"),"14")]) D$total_2015 <- rowSums(D[, paste0(c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"),"15")]) # 构建精简后的回归模型 model <- dynlm(entries17 ~ total_2014 + total_2015 + UR_region_2018 + entries16 + urad_2 + urad_3, data = D) summary(model)
三、用正则化回归获取预测系数
如果必须保留更多自变量用于预测,普通OLS无法估计,可使用岭回归或Lasso回归处理共线性和自由度问题:
library(glmnet) # 构建自变量矩阵与因变量 X <- model.matrix(entries17 ~ Jan14 + Feb14 + Mar14 + Apr14 + May14 + Jun14 + Jul14 + Aug14 + Sep14 + Oct14 + Nov14 + Dec14 + Jan15 + Feb15 + Mar15 + Apr15 + May15 + Jun15 + Jul15 + Aug15 + Sep15 + Oct15 + Nov15 + Dec15 + UR_region_2018 + entries16 + urad_2 + urad_3 + urad_4, data = D)[, -1] y <- D$entries17 # 交叉验证选择最优岭回归参数 cv_ridge <- cv.glmnet(X, y, alpha = 0) best_lambda <- cv_ridge$lambda.min # 获取最优系数 coef(cv_ridge, s = best_lambda)
关键注意事项
- 观测数必须远大于自变量数是回归分析的基本前提,4个观测无法支撑20+自变量的模型。
- 互斥虚拟变量组不能全部放入模型,否则会触发完全共线性。
- 正则化回归的系数适合用于预测,但变量解释性会下降,符合你的需求场景。
内容的提问来源于stack exchange,提问作者Zuzana
相关产品推荐
相关产品推荐

