使用dplyr创建含滞后值数值向量的数据框的技术求助
R语言批量生成滞后值向量并计算percent_rank解决方案
原始数据
data <- data.frame( A = c(10,20,30,40,50,60,70,80,90,100), B = c(110,120,130,140,150,160,170,180,190,200) )
核心需求
- 新增一列,每行存储当前A值、当前B值及B的N个滞后值组成的数值向量(示例中N=3,实际需支持200个滞后值),最终效果参考:
new_data <- data.frame( A = c(10,20,30,40,50,60,70,80,90,100), B = c(110,120,130,140,150,160,170,180,190,200), c = I(list(c(10,110,NA,NA,NA),c(20,120,110,NA,NA),c(30,130,120,110,NA),c(40,140,130,120,110),c(50,150,140,130,120),c(60,160,150,140,130),c(70,170,160,150,140),c(80,180,170,160,150),c(90,190,180,170,160),c(100,200,190,180,170)) ))
- 最终目标:计算每个A值在「当前A值 + 当前B值 + B的前N个滞后值」集合中的
percent_rank,判断A是否大于75分位数(即是否为异常值)。
遇到的问题
尝试用purrr::map生成滞后值,但在rowwise()环境中无法正确合并滞后值到目标向量,代码如下:
data %>% rowwise() %>% mutate(z = list(c(A,B,map_vec(1:3, ~lag(B,.x, default = NA)))))
解决方案
方案1:批量生成滞后值并组合向量
无需rowwise(),直接用pmap按行组合A、B和批量生成的滞后值:
library(dplyr) library(purrr) # 设置滞后数量(可改为200) lag_n <- 3 # 生成所有B的滞后值列表 lag_cols <- map(1:lag_n, ~lag(data$B, .x, default = NA)) # 按行组合A、B和所有滞后值 result <- data %>% mutate( combined_vec = pmap( list(A, B, !!!lag_cols), function(a, b, ...) c(a, b, ...) ) )
说明:!!!用于将滞后值列表展开为单独参数,pmap自动按行匹配对应的值并组合成向量。
方案2:直接计算percent_rank(跳过中间向量)
如果仅需计算排名,无需生成完整向量,直接按行提取值计算,效率更高(尤其适合200个滞后值的场景):
library(dplyr) lag_n <- 3 result <- data %>% mutate( a_percent_rank = map_dbl(row_number(), function(i) { # 提取当前A、当前B及前lag_n个B值(不足补NA) vals <- c( A[i], B[i], ifelse(i - 1 >= 1, B[i-1], NA), ifelse(i - 2 >= 1, B[i-2], NA), ifelse(i - 3 >= 1, B[i-3], NA) ) # 剔除NA后计算A的percent_rank clean_vals <- na.omit(vals) percent_rank(clean_vals)[which(clean_vals == A[i])] }), # 判断是否为异常值 is_outlier = a_percent_rank > 0.75 )
优化点:直接通过行索引提取所需值,避免生成大量中间列,处理大样本时更高效。
内容的提问来源于stack exchange,提问作者TheGoat
相关产品推荐
相关产品推荐

