You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

复现特征贡献瀑布图:解读多项逻辑回归参考类系数

多项逻辑回归系数解读与瀑布值计算指南(复刻《经济学人》可视化)

我想要复刻《经济学人》的一款优秀数据可视化作品——该作品用多项逻辑回归构建「特征贡献」瀑布图,展示不同群体的投票倾向。我手头有非政治类的相似数据,想做同类分析。下面是我写的可复现模拟代码,现在需要帮忙解读模型输出的系数,以此计算各预测变量水平的「瀑布值」。我知道这需要基于参考类对比,但《经济学人》的可视化看起来不受参考类选择的影响,推测是做了特殊的虚拟变量处理,求技术指导。

###### 加载包 ###### 
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 工党的优势比
  • 这种依赖参考类的输出直接用于可视化会受参考类选择影响,因此需要转换为绝对概率贡献(即瀑布值)

二、消除参考类影响的核心方法:基准群体差值法

《经济学人》的瀑布图本质是展示每个特征水平相对于「基准群体」的概率变化量,具体步骤:

  1. 定义基准群体:选择所有特征的参考水平组合(比如Age=18-29+Gender=Male),计算该群体对每个类别的预测概率
  2. 计算单特征变化的概率:对每个特征的非参考水平,替换基准群体的对应特征,得到新的预测概率
  3. 计算瀑布值:瀑布值 = 单特征变化后的概率 - 基准概率,这个值就是该特征水平对每个类别的贡献

三、基于现有模型的瀑布值计算代码

# 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:37:37