按周期剔除最低N值个体的R语言实现问题求助
逐周淘汰得分最低队伍的数据处理修正方案
问题回顾
需要实现:逐周从参赛队伍中移除得分最低的2支,预期结果为第1周剩10支、第2周8支、第3周6支、第4周4支,但现有代码仅第1周结果正确,后续周逻辑错误。
原代码问题点
原代码用map2搭配dplyr::lag()的思路错误,它只对比当前周和前一周的队伍,没有累积保留之前未被淘汰的队伍,导致后续周的筛选逻辑完全偏离需求。
修正方案
改用purrr::reduce()实现累积迭代:从第1周开始,每一步都基于上一轮留存的队伍,筛选当前周对应队伍的数据,再淘汰得分最低的2支,以此类推。
修正后的完整代码:
library(tibble) library(dplyr) library(purrr) library(stringr) set.seed(42) # 生成原始数据集 df <- tibble( week = rep(1:4, 12) %>% sort(), team = rep(str_c("team_", 1:12), 4), score = runif(48, 0, 100) %>% ceiling() ) %>% arrange(score) %>% split(.$week) # 实现累积淘汰逻辑 df_result <- reduce( .x = df, .init = df[[1]] %>% slice_max(score, n = -2, with_ties = FALSE), # 第1周先淘汰2支 .f = function(prev_remaining, current_week_data) { # 筛选当前周中,上一轮留存的队伍数据 current_remaining <- current_week_data %>% filter(team %in% prev_remaining$team) %>% slice_max(score, n = -2, with_ties = FALSE) # 再淘汰当前周得分最低的2支 return(current_remaining) } ) # 验证结果:查看各周剩余队伍数量 map(df_result, nrow)
代码说明
- 初始化:先处理第1周数据,用
slice_max(n = -2)直接淘汰得分最低的2支,得到初始留存队伍。 - 累积迭代:
reduce函数会依次将上一轮的留存队伍作为输入,和当前周的数据结合:- 先筛选出当前周中属于上一轮留存的队伍
- 再在这些队伍里淘汰得分最低的2支,作为下一轮的输入
- with_ties = FALSE:如果有队伍得分相同且刚好卡在淘汰线,这里选择只固定淘汰2支(可根据需求调整为
TRUE)。
结果验证
运行map(df_result, nrow)会输出[[1]] 10, [[2]] 8, [[3]] 6, [[4]] 4,完全符合预期。
内容的提问来源于stack exchange,提问作者M. Wood
相关产品推荐
相关产品推荐

