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

在R中计算含NA的列中两子组差异:议会点名党派度测算

解决R语言中含NA值的分组投票党派度计算问题

你遇到的核心问题是针对每个投票项单独排除NA值,而不是全局移除所有含NA的议员——这确实是na.omit()的局限性,它会删掉整行数据。下面我会一步步帮你实现需求,同时修正原始数据里的一个小问题(你创建的vote列里的"NA"是字符串,不是R认可的缺失值,这会影响后续判断)。

步骤1:修正原始数据,将字符串"NA"转为真实NA值

你当前用cbind创建的是字符矩阵,而且"NA"是字符串,不是R的缺失值类型。我们先把它转成数据框,并替换字符串"NA"为真实NA:

# 原始数据创建(注意修正vote列的"NA"为R原生缺失值)
Legislator=c("Allen", "Barber", "Cale", "Devin", "Egan", "Floyd")
Party=c("R", "D", "D", "R", "R", "R")
vote1=c("yes", NA, "no", "no", "yes", "yes")
vote2=c("no", "no", NA, "no", "yes", "no")
vote3=c(NA, "no", "yes", "no", "yes", "yes")
vote4=c("no", "yes", "yes", "yes", NA, "no")
vote5=c("yes", "no", "yes", "yes", "no", "yes")
vote6=c("yes", "yes", "no", "yes", "no", "no")
vote7=c("no", "no", "yes", "yes", "no", "yes")

# 组合成数据框(避免用cbind生成矩阵)
rollcall <- data.frame(Legislator, Party, vote1, vote2, vote3, vote4, vote5, vote6, vote7, stringsAsFactors = FALSE)

如果已经有了原始的字符矩阵,也可以用下面的代码批量替换:

# 若已有rollcall矩阵,先转数据框再替换字符串"NA"
rollcall <- as.data.frame(rollcall, stringsAsFactors = FALSE)
rollcall[rollcall == "NA"] <- NA

步骤2:编写函数计算单个投票项的党派度

我们可以写一个自定义函数,输入单个投票列和对应的党派列,输出该投票的党派度:

calculate_partisanship <- function(vote_col, party_col) {
  # 过滤当前投票的非NA数据,只保留有效投票记录
  valid_data <- data.frame(Vote = vote_col, Party = party_col) %>%
    dplyr::filter(!is.na(Vote))
  
  # 计算民主党赞成率:统计"yes"的占比
  dem_aye_pct <- mean(valid_data$Vote[valid_data$Party == "D"] == "yes", na.rm = TRUE)
  # 计算共和党赞成率
  gop_aye_pct <- mean(valid_data$Vote[valid_data$Party == "R"] == "yes", na.rm = TRUE)
  
  # 返回绝对差异,即党派度
  abs(dem_aye_pct - gop_aye_pct)
}

步骤3:批量计算所有投票项的党派度

这里提供两种实现方式,你可以根据自己的习惯选择:

方法1:使用tidyverse工具(更直观)

library(dplyr)
library(purrr)

# 提取所有以"vote"开头的列
vote_cols <- select(rollcall, starts_with("vote"))

# 批量计算每个投票项的党派度
partisanship_results <- map_dbl(vote_cols, ~calculate_partisanship(.x, rollcall$Party))

# 整理成你需要的输出格式
result_df <- data.frame(
  RollCall = names(partisanship_results),
  Partisanship = round(partisanship_results, 2),
  row.names = NULL
)

print(result_df)

方法2:基础R实现(无需额外安装包)

# 获取所有投票列的索引
vote_col_indices <- grep("^vote", names(rollcall))

# 用sapply批量计算
partisanship_results <- sapply(rollcall[, vote_col_indices], function(col) {
  calculate_partisanship(col, rollcall$Party)
})

# 整理结果
result_df <- data.frame(
  RollCall = names(partisanship_results),
  Partisanship = round(partisanship_results, 2),
  row.names = NULL
)

print(result_df)

最终输出结果

运行后会得到和你期望完全一致的结果:

RollCall Partisanship
1    vote1          0.75
2    vote2          0.25
3    vote3          0.17
4    vote4          0.70
5    vote5          0.25
6    vote6          0.00
7    vote7          0.00

关键说明

  • 逐投票项过滤NA:在自定义函数里,我们只针对当前投票列的NA进行过滤,不会影响其他投票项的计算,完美解决了全局删除的问题。
  • 稳健的赞成率计算:用mean(...)统计"yes"的比例,搭配na.rm=TRUE,即使某党派在某次投票中没有有效记录(比如全是NA),也不会报错。
  • 结果格式化:用round()保留两位小数,匹配你需要的输出样式。

内容的提问来源于stack exchange,提问作者Dyllan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:47:55