如何用zoo/slider计算points相对values滚动4窗口的百分位秩?
滚动窗口百分位秩计算方案
需求:为给定数据框新增percentile_rank列,每行的取值逻辑是:计算该行points值在values列**当前行及前3行(共4个值)**滚动窗口中的百分位秩。
给定数据:
df <- data.frame( type = rep(c("A","B"),times = 10), values = c(16,16,16,16,16,17,18,18,20,20,45,44,45,44,45,47,45,46,47,50), points = c(20,14,34,44,40,50,44,34,43,23,60,61,62,63,64,65,66,67,68,69) )
方法1:使用slider包
slider的slide_dbl函数支持灵活定义滚动窗口范围,直接对数据框的子窗口操作:
library(slider) df$percentile_rank <- slide_dbl( .x = df, .f = function(window) { window_values <- window$values current_point <- window$points[nrow(window)] # 计算0-100范围的百分位秩 ecdf(window_values)(current_point) * 100 }, .before = 3, # 包含当前行前3行 .after = 0, # 不包含当前行之后的行 .complete = FALSE # 允许窗口不足4行(前3行按实际行数计算) )
方法2:使用zoo包
zoo::rollapply通过矩阵组合values和points,指定右对齐窗口实现需求:
library(zoo) # 组合values和points为矩阵,方便窗口内同时获取两个列的数据 data_matrix <- cbind(df$values, df$points) df$percentile_rank_zoo <- rollapply( data_matrix, width = 4, FUN = function(window_mat) { window_values <- window_mat[, 1] current_point <- window_mat[nrow(window_mat), 2] ecdf(window_values)(current_point) * 100 }, align = "right", # 窗口右对齐,确保当前行是窗口最后一个元素 partial = TRUE # 允许窗口不足4行时计算,保留前3行的结果 )
说明
- 百分位秩通过经验累积分布函数
ecdf计算,返回0-100的百分比数值; - 两种方法的核心逻辑一致:对每个滚动窗口内的
values集合,计算当前行points值在该集合中的相对位置; - 若不需要前3行的部分窗口结果,可将
.complete = TRUE(slider)或移除partial = TRUE并设置fill = NA(zoo)。
内容的提问来源于stack exchange,提问作者TheGoat
相关产品推荐
相关产品推荐

