如何在R中无需嵌套for循环生成立法者投票相似度矩阵
R无嵌套循环实现投票相似度矩阵方法
以下两种实现都完全不需要写嵌套for循环,性能远高于循环实现:
方法1:Base R原生实现(无需第三方包)
直接用outer函数完成两两立法者的投票匹配,代码简洁适配中小规模数据集:
# 1. 构造你的投票矩阵示例 vote_mat <- matrix( c(1,1,1,2, 1,1,0,0, 2,2,2,2, 2,2,0,0), nrow = 4, byrow = TRUE, dimnames = list(paste0("L",1:4), paste0("I",1:4)) ) # 2. 单个议题相似度矩阵生成函数 get_sim_mat <- function(issue_votes) { # 两两计算:都出席且投票相同返回1,否则返回0 sim <- outer(issue_votes, issue_votes, function(x,y) { as.integer(x != 0 & y != 0 & x == y) }) # 对角线设为空(匹配你的输出示例,不需要可删掉这行) diag(sim) <- NA dimnames(sim) <- list(names(issue_votes), names(issue_votes)) return(sim) } # 3. 测试第一个议题I1的输出 sim_I1 <- get_sim_mat(vote_mat[,"I1"]) print(sim_I1) # 4. 批量生成所有议题的相似度矩阵(返回列表,按议题名取数即可) all_sim <- lapply(colnames(vote_mat), function(col) get_sim_mat(vote_mat[,col])) names(all_sim) <- colnames(vote_mat) # 取I1的结果直接调用 all_sim$I1
方法2:高性能实现(适配>1000名立法者的大规模数据集)
用矩阵运算替代函数映射,速度比方法1快2~10倍:
get_sim_mat_fast <- function(issue_votes) { # 生成出席掩码矩阵:两人都出席的位置为1 present <- as.integer(issue_votes != 0) present_mat <- tcrossprod(present) # 生成投票相同掩码矩阵:两人都投赞成/都投反对的位置为1 same_yea <- tcrossprod(as.integer(issue_votes == 1)) same_nay <- tcrossprod(as.integer(issue_votes == 2)) same_vote <- same_yea + same_nay # 合并结果 sim <- as.integer(present_mat & same_vote) dim(sim) <- dim(present_mat) diag(sim) <- NA dimnames(sim) <- list(names(issue_votes), names(issue_votes)) return(sim) }
调用方式和方法1完全一致。
内容的提问来源于stack exchange,提问作者snitsova
相关产品推荐
相关产品推荐

