如何输出GLM全部线性预测项且行列数匹配预期需求?
解决方案
方法1:直接对predict的terms结果反中心化(最简单,无需额外包)
predict.glm输出type="terms"结果时默认做了中心化,也就是每列减去了该项的全样本均值,我们只需要将对应均值加回即可得到未中心化的原始项贡献,代码如下:
data <- data.frame(var1 = rep(c("a","b","c"),4), var2 = rep(c("d","e"),6), var3 = 1:12) model <- glm(var3 ~ var1*var2, data = data) # 获取默认中心化的terms结果 centered_terms <- predict(model, type = "terms") # 提取结果中存储的每一项的均值属性 term_means <- attr(centered_terms, "means") # 对每一列加回对应均值,得到未中心化的项贡献 uncentered_terms <- sweep(centered_terms, 2, term_means, FUN = "+")
输出的uncentered_terms行数与原始数据一致,列数与模型项数完全匹配,列名就是公式中定义的项名。
方法2:手动按模型项分组求和(更灵活可控)
如果你需要完全自定义计算逻辑,可以通过模型矩阵的assign属性匹配每一列对应的模型项,分组求和得到对应结果:
# 计算每个系数对应的贡献矩阵 coef_contrib <- t(coef(model) * t(model.matrix(model))) # 获取模型矩阵每一列对应的项编号(0为截距,1、2、3对应三个模型项) term_assign <- attr(model.matrix(model), "assign") # 获取模型项的名称 term_names <- labels(terms(model)) # 按项分组求和 uncentered_terms <- do.call( cbind, lapply(seq_along(term_names), function(i) { rowSums(coef_contrib[, term_assign == i, drop = FALSE]) }) ) colnames(uncentered_terms) <- term_names
结果验证
可以通过以下代码验证结果正确性:
# 验证两种方法输出结果一致 all.equal(uncentered_terms, uncentered_terms, check.attributes = FALSE) # 验证项贡献总和加截距等于模型预测值 all.equal( rowSums(uncentered_terms) + coef(model)[["(Intercept)"]], as.numeric(predict(model, type = "response")) )
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

