基于线性回归系数对全量数据框执行线性变换的方法及因子变量系数匹配问题
嗨,我来帮你搞定这个问题!你碰到的核心卡点其实是因子变量在回归时会被自动转换成哑变量,所以回归输出的系数数量和原数据的列数没法直接对应——比如你的gender是二分类因子,回归里会生成一个哑变量(比如genderF,参考水平是M),race是多分类因子,会生成多个哑变量,这就导致系数数和原列数对不上了。
下面给你两种简单靠谱的解决办法,都能轻松把回归的线性变换应用到整个regression.df数据集上:
方法一:用predict()函数(最省心推荐)
你之前误解了predict()的能力哦!它不仅能对训练数据(也就是你过滤后的处理组)生成预测值,只要新数据的列名和训练时的列名一致,它就能自动适配并生成结果,完全不用手动处理因子编码的问题。
直接看代码:
# 你的原始回归代码不变 results.lm <- lm(income ~ gender + race + age, data = regression.df %>% filter(treatment == "Treatment")) # 对全量数据生成线性变换后的结果(也就是回归的预测值) regression.df$linear_transform <- predict(results.lm, newdata = regression.df)
这个方法的好处是:R会自动沿用回归模型中使用的因子参考水平、哑变量编码规则,对全量数据做完全一致的转换,完美匹配系数,根本不会出现匹配错误的问题,省心又高效。
方法二:手动构建线性变换(适合想搞懂底层逻辑)
如果你想手动实现这个过程,核心是先把全量数据转换成和回归模型一模一样的哑变量矩阵,再和系数做矩阵乘法:
# 1. 提取回归的所有系数(包括截距) model_coefs <- coef(results.lm) # 2. 对全量数据生成和回归模型结构一致的设计矩阵 # 这里的公式要和你做回归时的公式完全相同 full_design_matrix <- model.matrix(income ~ gender + race + age, data = regression.df) # 3. 矩阵乘法计算线性变换结果 regression.df$linear_transform_manual <- full_design_matrix %*% model_coefs
这里model.matrix()生成的矩阵,和你做回归时处理组数据的设计矩阵结构完全一致——因子的哑变量、参考水平都和回归时保持同步,所以和系数向量相乘后,就能得到正确的线性组合结果。
如果你只想计算不含截距的线性变换(就像你之前过滤掉截距的操作),可以稍微调整一下:
# 去掉截距项的系数和设计矩阵列 coefs_no_intercept <- model_coefs[names(model_coefs) != "(Intercept)"] design_matrix_no_intercept <- full_design_matrix[, colnames(full_design_matrix) != "(Intercept)"] # 计算不含截距的线性变换 regression.df$linear_transform_no_intercept <- design_matrix_no_intercept %*% coefs_no_intercept
为什么你之前的系数匹配会出问题?
再给你捋清楚根源:原数据里的gender和race是因子列,当你用lm()做回归时,R会默认把因子的第一个水平设为参考水平,然后把其他水平转换成哑变量(比如race有6个水平,就会生成5个哑变量)。所以回归输出的系数是这些哑变量的系数,而不是原因子列本身的系数,直接和原数据列匹配自然会对不上啦~
备注:内容来源于stack exchange,提问作者Sarah Medoff

