复现特征贡献瀑布图:解读多项逻辑回归参考类系数
多项逻辑回归系数解读与瀑布值计算指南(复刻《经济学人》可视化)
我想要复刻《经济学人》的一款优秀数据可视化作品——该作品用多项逻辑回归构建「特征贡献」瀑布图,展示不同群体的投票倾向。我手头有非政治类的相似数据,想做同类分析。下面是我写的可复现模拟代码,现在需要帮忙解读模型输出的系数,以此计算各预测变量水平的「瀑布值」。我知道这需要基于参考类对比,但《经济学人》的可视化看起来不受参考类选择的影响,推测是做了特殊的虚拟变量处理,求技术指导。
###### 加载包 ###### require(tidyverse) require(nnet) ###### 创建模拟数据集 ###### set.seed(123) # 设置随机种子保证可复现 # 生成投票意向的函数:根据年龄组和性别分配不同概率 generate_voting_intention <- function(age_bracket, gender) { # 工党在各年龄组的基础概率 base_prob_labour <- c("18-29"=0.45, "30-39"=0.40, "40-49"=0.38, "50-64"=0.36, "65+"=0.35) # 性别对工党概率的调整:女性增加5%概率 gender_mod_labour <- ifelse(gender == "Female", 0.05, 0) prob_labour <- base_prob_labour[age_bracket] + gender_mod_labour # 保守党在各年龄组的基础概率 base_prob_conservative <- c("18-29"=0.25, "30-39"=0.30, "40-49"=0.32, "50-64"=0.34, "65+"=0.35) # 本例中性别不影响保守党概率 prob_conservative <- base_prob_conservative[age_bracket] # 自由民主党的概率为剩余部分 prob_lib_dems <- 1 - prob_labour - prob_conservative # 根据概率抽样投票意向 sample(c("Labour", "Conservative", "Lib Dems"), size = 1, prob = c(prob_labour, prob_conservative, prob_lib_dems)) } # 创建调查数据集的函数 create_survey_data <- function(n) { age_brackets <- c("18-29", "30-39", "40-49", "50-64", "65+") genders <- c("Male", "Female") # 抽样年龄和性别 ages <- sample(age_brackets, n, replace = TRUE) genders <- sample(genders, n, replace = TRUE) # 生成每个受访者的投票意向 voting_intention <- mapply(generate_voting_intention, age_bracket = ages, gender = genders) # 组合成数据框 data.frame( Age = ages, Gender = genders, VotingIntention = voting_intention, stringsAsFactors = FALSE ) } # 生成1000个受访者的模拟数据 survey_data <- create_survey_data(1000) ###### 构建投票意向模型 ###### vote_mod<-multinom(VotingIntention~Age + Gender, data=survey_data) tidy_vote_mod<-tidy(vote_mod,exponentiate = TRUE)
一、多项逻辑回归系数的本质
multinom输出的系数是相对参考类的对数优势比(指数化后为优势比),默认以因变量的第一个类别作为参考类(本例中是Labour):
- 比如
Conservative类别下的Age30-39系数,代表30-39岁群体相对于参考年龄段(18-29岁)选择保守党 vs 工党的优势比 - 这种依赖参考类的输出直接用于可视化会受参考类选择影响,因此需要转换为绝对概率贡献(即瀑布值)
二、消除参考类影响的核心方法:基准群体差值法
《经济学人》的瀑布图本质是展示每个特征水平相对于「基准群体」的概率变化量,具体步骤:
- 定义基准群体:选择所有特征的参考水平组合(比如
Age=18-29+Gender=Male),计算该群体对每个类别的预测概率 - 计算单特征变化的概率:对每个特征的非参考水平,替换基准群体的对应特征,得到新的预测概率
- 计算瀑布值:瀑布值 = 单特征变化后的概率 - 基准概率,这个值就是该特征水平对每个类别的贡献
三、基于现有模型的瀑布值计算代码
# 1. 定义基准群体(所有特征取参考水平) baseline <- data.frame(Age = "18-29", Gender = "Male") # 计算基准群体的预测概率 baseline_probs <- predict(vote_mod, newdata = baseline, type = "probs") %>% t() %>% as.data.frame() colnames(baseline_probs) <- "baseline_prob" # 2. 生成所有单特征变化的场景(只改变一个特征,其余保持基准) single_feature_changes <- rbind( # 仅年龄变化,性别保持基准 data.frame(Age = setdiff(unique(survey_data$Age), "18-29"), Gender = "Male"), # 仅性别变化,年龄保持基准 data.frame(Age = "18-29", Gender = setdiff(unique(survey_data$Gender), "Male")) ) # 3. 计算每个场景的预测概率 feature_probs <- predict(vote_mod, newdata = single_feature_changes, type = "probs") %>% as.data.frame() # 4. 合并特征信息与概率,计算瀑布值 feature_contributions <- cbind(single_feature_changes, feature_probs) %>% mutate( Labour_contribution = Labour - baseline_probs["Labour", "baseline_prob"], Conservative_contribution = Conservative - baseline_probs["Conservative", "baseline_prob"], LibDems_contribution = `Lib Dems` - baseline_probs["Lib Dems", "baseline_prob"] ) # 查看结果 print(feature_contributions)
四、复刻《经济学人》风格的瀑布图
用ggplot2绘制特征贡献瀑布图:
# 将数据转换为长格式,方便绘图 contributions_long <- feature_contributions %>% select(Age, Gender, Labour_contribution, Conservative_contribution, LibDems_contribution) %>% pivot_longer( cols = ends_with("contribution"), names_to = "Party", values_to = "Contribution" ) %>% mutate(Party = str_remove(Party, "_contribution")) # 绘制瀑布图 ggplot(contributions_long, aes(x = Party, y = Contribution, fill = interaction(Age, Gender))) + geom_col(position = "dodge", alpha = 0.8) + geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") + labs( title = "各特征水平对投票倾向的贡献", subtitle = "相对于基准群体(18-29岁男性)的概率变化", y = "概率变化值", x = "政党", fill = "特征组合" ) + theme_minimal() + theme(legend.position = "bottom")
内容的提问来源于stack exchange,提问作者Robin Sheridan
相关产品推荐
相关产品推荐

