R语言中lm()含+0公式时,如何输出所有分类变量的全部类别系数?
问题解答
问题原因
当你使用a ~ . + 0调用lm()时,R的默认行为是:
- 对第一个分类变量(示例中的
c)保留所有水平的系数(因为去掉了截距,R会用第一个分类变量的所有水平替代截距的作用); - 对后续的分类变量(示例中的
d)仍采用默认的treatment编码——每个分类变量会省略一个水平作为参照组,仅返回k-1个水平的系数,以此避免模型出现完全共线性。
解决方案
要让所有分类变量的每个水平都返回系数,需为每个分类变量显式指定无参照的对比编码,通过lm()的contrasts参数实现:
手动指定对比编码
# 为分类变量c和d设置无参照的treatment编码(保留所有水平) mod2 <- lm(a ~ . + 0, data = dat1, contrasts = list( c = contr.treatment(nlevels(dat1$c), base = 0), d = contr.treatment(nlevels(dat1$d), base = 0) )) # 查看所有系数 coef(mod2)
自动识别分类变量并设置编码
如果数据中有多个分类变量,可自动生成对比列表:
# 筛选出所有因子类型的变量 factor_vars <- names(dat1)[sapply(dat1, is.factor)] # 为每个因子生成无参照的对比编码 contrast_list <- lapply(factor_vars, function(var) { contr.treatment(nlevels(dat1[[var]]), base = 0) }) names(contrast_list) <- factor_vars # 拟合模型 mod3 <- lm(a ~ . + 0, data = dat1, contrasts = contrast_list) # 查看系数 coef(mod3)
注意事项
这种设置会导致模型出现完全共线性(例如每个分类变量的所有水平dummy变量之和为全1向量),lm()会通过广义逆计算系数。此时系数的解释与常规模型不同:每个系数代表该水平相对于全局均值的效应,而非相对于参照组的效应。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

