使用dplyr的top_n分组筛选时,如何用第二指标打破平局?
分组筛选Top N并处理平局问题
需求是按分类列分组后,基于主指标筛选Top N数据,同时用次指标打破平局,避免因平局导致结果行数过多。当前使用top_n无法处理多指标平局的情况,需要替代方案。
示例数据
library(dplyr) df = data.frame(category = c(rep("red",4), rep("green",4), rep("blue",4)), metric1 = c(1,1,2,3, 1,2,2,3, 1,2,1,3), metric2 = c(rep(1:4,3))) head(df)
输出:
category metric1 metric2 1 red 1 1 2 red 1 2 3 red 2 3 4 red 3 4 5 green 1 1 6 green 2 2
使用top_n的问题:执行以下代码后,green组因metric1=2出现两行结果,不符合仅保留一行的需求。
df %>% group_by(category) %>% top_n(2, wt=metric1)
解决方案
方法1:使用slice_max(dplyr 1.0.0+版本推荐)
slice_max支持传入多指标排序规则,先按主指标排序,再用次指标打破平局,同时通过参数直接截断平局结果。
df %>% group_by(category) %>% slice_max(order_by = c(metric1, metric2), n = 2, with_ties = FALSE)
order_by = c(metric1, metric2):优先按metric1降序排序,次指标metric2降序打破平局(若需升序打破平局,改为c(metric1, metric2)即可)with_ties = FALSE:直接截断平局数据,仅保留前N行
方法2:先排序再切片(类似Python Lambda排序逻辑)
通过先按多指标优先级排序,再取前N行,逻辑直观易懂:
df %>% group_by(category) %>% arrange(desc(metric1), desc(metric2)) %>% # 先按主指标降序,再按次指标降序 slice_head(n = 2)
方法3:手动计算组合排名处理平局
如果需要更灵活的排名规则,可通过给次指标添加小权重生成唯一排名,再筛选:
df %>% group_by(category) %>% mutate(rank = dense_rank(desc(metric1)) + min_rank(desc(metric2))/100) %>% # 主指标排名+次指标小权重排名 filter(rank <= 2) %>% select(-rank)
内容的提问来源于stack exchange,提问作者Matthew Kozubov
相关产品推荐
相关产品推荐

