基于R dataframe的游戏玩家多分值加权得分高效计算问题咨询
解法
1. tidyverse易维护写法
适合中小数据集,逻辑清晰易调整,无需手动对应得分列数量,修改max_score参数即可适配最高100分的需求:
library(dplyr) library(tidyr) # 示例数据 df <- data.frame(player1 = c(1,2,1), player2 = c(2,2,1), player3 = c(2,2,2), weightplayer1=c(0.7,0.8,0.7), weightplayer2 = c(0.6,0.1,0.6), weightplayer3=c(0.2,0.7,0.2)) max_score <- 100 # 实际场景可直接修改为最高分,比如100 result <- df %>% mutate(game_id = row_number()) %>% pivot_longer(cols = starts_with("player"), names_to = "player", values_to = "score") %>% pivot_longer(cols = starts_with("weightplayer"), names_to = "weight_player", values_to = "weight") %>% filter(sub("player", "", player) == sub("weightplayer", "", weight_player)) %>% group_by(game_id, score) %>% summarise(total_weight = sum(weight), .groups = "drop") %>% complete(score = 1:max_score, fill = list(total_weight = 0)) %>% pivot_wider(names_from = score, values_from = total_weight, names_prefix = "weighted", names_suffix = "scores") %>% right_join(df %>% mutate(game_id = row_number()), by = "game_id") %>% select(-game_id, all_of(starts_with("player")), all_of(starts_with("weightplayer")), everything())
2. base R高性能写法
适合超大数据量场景,运算效率更高,无需安装第三方依赖:
# 示例数据同上 df <- data.frame(player1 = c(1,2,1), player2 = c(2,2,1), player3 = c(2,2,2), weightplayer1=c(0.7,0.8,0.7), weightplayer2 = c(0.6,0.1,0.6), weightplayer3=c(0.2,0.7,0.2)) max_score <- 100 # 按需修改最高分 # 提取得分、权重矩阵 score_cols <- grep("^player\\d+$", colnames(df)) weight_cols <- grep("^weightplayer\\d+$", colnames(df)) score_mat <- as.matrix(df[, score_cols]) weight_mat <- as.matrix(df[, weight_cols]) # 初始化加权得分结果矩阵 weighted_res <- matrix(0, nrow = nrow(df), ncol = max_score, dimnames = list(NULL, paste0("weighted", 1:max_score, "scores"))) # 逐行统计各得分对应的权重和 for (i in seq_len(nrow(df))) { score_sum <- tapply(weight_mat[i, ], score_mat[i, ], sum) weighted_res[i, as.integer(names(score_sum))] <- score_sum } # 合并回原数据 result <- cbind(df, weighted_res)
以上两种方法运行示例数据(将max_score设为2)时,输出结果与你给出的预期完全一致。
内容的提问来源于stack exchange,提问作者scarlett rouge
相关产品推荐
相关产品推荐

