如何用R基础包生成玩家对战结果拼接的双向表?
解决方案
可以基于你提到的tapply思路优化,补上NA处理、对角线填充和矩阵格式化的步骤,用R基础包就能实现:
步骤1:预处理数据,替换NA
先把数据里的NA替换成你需要的占位符(示例里是.):
hch <- intToUtf8(0x00BD) idx <- data.frame( player = c(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 4, 1), opponent = c(4, 3, 2, 1, 2, 1, 4, 3, 3, 4, 1, 2, 1, 4), result = c(hch, 1, 0, hch, 0, 0, 1, 0, NA, 1, NA, 0, 1, 0) ) # 替换NA为指定符号 idx$result[is.na(idx$result)] <- "."
步骤2:分组拼接对战结果
用tapply按player和opponent分组,把同组的结果拼接成字符串:
# 按玩家和对手分组拼接结果 res <- tapply(idx$result, list(idx$player, idx$opponent), paste0, collapse = "")
步骤3:转换为矩阵并格式化
把tapply的结果转换成标准矩阵,填充对角线为x,确保行列对应所有玩家:
# 获取所有玩家编号 players <- sort(unique(c(idx$player, idx$opponent))) # 创建空矩阵 res_mat <- matrix("", nrow = length(players), ncol = length(players), dimnames = list(players, players)) # 填充拼接结果 res_mat[rownames(res), colnames(res)] <- res # 对角线设为x diag(res_mat) <- "x"
运行后得到的res_mat就是你要的结果:
# 1 2 3 4 # 1 "x" "0" "." "½0" # 2 "0" "x" "1" "1" # 3 "." "0" "x" "1" # 4 "½1" "0" "0" "x"
封装成函数
如果需要重复使用,可以把这些步骤封装成函数:
build_battle_matrix <- function(data) { # 替换NA为. data$result[is.na(data$result)] <- "." # 分组拼接 res <- tapply(data$result, list(data$player, data$opponent), paste0, collapse = "") # 获取所有玩家 players <- sort(unique(c(data$player, data$opponent))) # 创建矩阵并填充 res_mat <- matrix("", nrow = length(players), ncol = length(players), dimnames = list(players, players)) res_mat[rownames(res), colnames(res)] <- res # 对角线设为x diag(res_mat) <- "x" return(res_mat) } # 使用示例 build_battle_matrix(idx)
这个方案比循环简洁,完全用基础包实现,也符合你要求的用聚合类函数(tapply)的思路。
内容的提问来源于stack exchange,提问作者clp
相关产品推荐
相关产品推荐

