如何基于投票记录DataFrame生成用户相似度矩阵
计算投票用户相似度矩阵的实现方法
核心思路
把长格式的投票数据转换为用户-投票的宽格式矩阵,再对每对用户统计共同投票中响应一致的次数占比,最终生成对角线为1的对称相似度矩阵。
实现步骤
假设你的数据集已加载为vote_df,以下是具体代码实现:
1. 数据预处理:转换为宽格式
先将session和sessionvote合并为唯一投票标识,再转成宽格式——每行对应一个用户,每列对应一个投票,单元格存储用户的投票响应:
library(tidyverse) # 生成唯一投票ID vote_wide <- vote_df %>% mutate(vote_id = paste(session, sessionvote, sep = "_")) %>% select(name, vote_id, voter_response) %>% pivot_wider(names_from = vote_id, values_from = voter_response)
2. 计算两两用户相似度
借助proxy包自定义相似度计算逻辑,快速生成矩阵:
library(proxy) # 自定义相似度函数:一致响应次数 ÷ 共同参与投票总数 similarity_fun <- function(x, y) { # 筛选双方都参与的投票(排除NA值) common_votes <- !is.na(x) & !is.na(y) if(sum(common_votes) == 0) return(0) # 无共同投票时相似度为0 # 统计响应一致的次数 match_count <- sum(x[common_votes] == y[common_votes]) # 返回相似度得分 match_count / sum(common_votes) } # 计算相似度矩阵并转换为对称格式 sim_matrix <- as.matrix(proxy::dist(vote_wide[, -1], method = similarity_fun)) # 设置矩阵的行名和列名为用户名 rownames(sim_matrix) <- vote_wide$name colnames(sim_matrix) <- vote_wide$name # 将对角线设为1(用户与自身相似度为1) diag(sim_matrix) <- 1
3. 结果说明
最终的sim_matrix即为目标矩阵:
- 对角线值全为1(用户与自身的相似度固定为1)
- 其他位置为对应两位用户的相似度得分,比如
sim_matrix["Tim", "Larry"]会返回示例中的0.66左右的值。
替代实现(Base R版本)
如果不想依赖第三方包,可手动遍历计算:
# 获取所有唯一用户列表 users <- unique(vote_df$name) n_users <- length(users) # 初始化相似度矩阵,对角线默认设为1 sim_matrix <- matrix(1, nrow = n_users, ncol = n_users, dimnames = list(users, users)) # 遍历每一对用户计算相似度 for(i in 1:(n_users-1)) { for(j in (i+1):n_users) { user1 <- users[i] user2 <- users[j] # 提取两位用户的投票数据 u1_votes <- subset(vote_df, name == user1, select = c(vote_id, voter_response)) u2_votes <- subset(vote_df, name == user2, select = c(vote_id, voter_response)) # 合并双方共同参与的投票 common_votes <- merge(u1_votes, u2_votes, by = "vote_id") if(nrow(common_votes) == 0) { sim_score <- 0 } else { sim_score <- sum(common_votes$voter_response.x == common_votes$voter_response.y) / nrow(common_votes) } # 对称填充矩阵 sim_matrix[i,j] <- sim_score sim_matrix[j,i] <- sim_score } }
内容的提问来源于stack exchange,提问作者lwe
相关产品推荐
相关产品推荐

