R语言自动化按赛季选取各列Top3值并计算总分的问题
问题
示例数据
df<-data.frame(Season=rep(2001:2003,each=5), A=c(1:15), B = rep(10,15), C=c(15:1), Pts = seq(150,10,-10)) df
需求:按Season分组,分别对变量A、B、C选取每组Top3的记录,计算对应Pts的总分。手动处理A列时用group_by()+slice_max()可行,但B列全是重复值,必须加A列作为破局者才能保证每组只选3条记录。
尝试用函数+循环自动化处理时,出现错误:
Caused by error:! order_by must have size 5, not size 15
疑问:
- 数据框引用是否正确?
- 有没有更优的方法处理重复值,不用把部分变量排除在循环外当破局者?
解答
1. 数据框引用问题
这个错误的核心是你在循环里调用slice_max时,order_by参数引用的是整个原数据框的列(长度15),而不是分组后每组的列(每组长度5)。
比如如果循环里写的是slice_max(order_by = df[[var]], n=3),就会触发这个错误——分组后每个子组只有5行,但你传了整个15行的列进去。正确的做法是用dplyr的.data代词来引用当前分组环境中的变量,比如slice_max(order_by = .data[[var]], n=3),这样就能正确取到每组内的对应变量列。
2. 处理重复值的更优方法
不用单独依赖A列当破局者,有两种更通用的方式:
方式一:利用row_number()作为内置破局变量
分组后,先按目标变量降序排序,再按每组内的行号(row_number())升序排序,这样即使目标变量全重复,行号的唯一性也能保证稳定选出前3条记录:
library(dplyr) calc_top3_pts <- function(var_name) { df %>% group_by(Season) %>% arrange(desc(.data[[var_name]]), row_number()) %>% slice_head(n=3) %>% summarise(total_pts = sum(Pts)) %>% mutate(variable = var_name) } # 循环处理A-C变量 purrr::map_dfr(c("A", "B", "C"), calc_top3_pts)
方式二:用slice_max的多变量排序
在slice_max的order_by里同时指定目标变量和row_number(),不用额外arrange:
calc_top3_pts <- function(var_name) { df %>% group_by(Season) %>% slice_max(order_by = c(.data[[var_name]], row_number()), n=3, with_ties=FALSE) %>% summarise(total_pts = sum(Pts)) %>% mutate(variable = var_name) } purrr::map_dfr(c("A", "B", "C"), calc_top3_pts)
这两种方法都不需要依赖外部的破局变量(比如A列),不管目标变量有没有重复,都能稳定每组选3条记录,计算对应Pts的总分。
内容的提问来源于stack exchange,提问作者Jberry
相关产品推荐
相关产品推荐

