使用Tidyverse对Tibble中指定回溯窗口内的数值分组排名
基于滑动窗口的分组排名实现(Tidyverse)
问题描述
现有如下Tibble数据:
set.seed(123) tib <- tibble( target = c(rep(1, 20), rep(2, 20)), session = rep(1:20, 2), value = runif(n = 40, min = 40, max = 100) )
需求:按target分组,对每个session对应的value,基于**其之前10个session(含当前)**的数值进行排名(例如第15个session的数值,需在第5-15个session的数值范围内排名;若session不足10个,则取从第1个到当前session的范围)。尝试过row_number()等排名函数,但无法设置回溯窗口,需要用Tidyverse工具实现。
解决方案
方法一:使用slider包(推荐,高效)
slider是Tidyverse生态中专门处理滑动窗口操作的工具包,适配此类场景。
首先加载依赖包:
library(tidyverse) library(slider)
实现代码:
tib_ranked <- tib %>% # 按target分组 group_by(target) %>% # 确保组内session按顺序排列 arrange(session, .by_group = TRUE) %>% # 计算滑动窗口内的排名 mutate( window_rank = slide_index_rank( x = value, # 待排名的数值列 i = session, # 作为窗口索引的列 .before = 9, # 取当前session之前的9个元素,加当前共10个 .complete = FALSE # 允许窗口不足10个的情况(前9个session) ) ) %>% ungroup()
方法二:纯dplyr实现(无需额外包,适合小数据集)
如果不想加载额外包,可以用rowwise()结合slice()实现,不过效率较低,仅推荐小数据集使用:
tib_ranked_alt <- tib %>% group_by(target) %>% arrange(session, .by_group = TRUE) %>% rowwise() %>% mutate( # 确定窗口范围:从当前行往前9行(最少第1行)到当前行 window_values = list(slice(cur_data(), max(1, row_number()-9):row_number())$value), # 计算当前value在窗口内的排名 window_rank = rank(value, data = window_values) ) %>% ungroup() %>% # 可选:移除临时列window_values select(-window_values)
结果验证
可以筛选某一target的结果查看,比如target=1的前15条数据:
tib_ranked %>% filter(target == 1) %>% select(session, value, window_rank)
输出会显示每个session的value在对应滑动窗口内的排名,符合需求。
内容的提问来源于stack exchange,提问作者Zachary Morford
相关产品推荐
相关产品推荐

