You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中用rollapply高效实现带min过滤的滚动均值计算

问题描述

现有如下data.table数据,需按x的唯一值分组处理:

DT <- data.table(
 N = 1:16,
 x = c(11,11,11,11,11,11,11,11,21,21,21,21,21,21,21,21), 
 y = rep(1:4,4,4,4,1:4,4,4,4), 
 z = c(53,71,27,64,43,62,61,85,44,56,23,37,31,48,80,38),
 min = c(2.74,2.77,2.23,2.98,2.25,2.48,2.46,2.22,3.07,
        3.08,3.81,3.31,3.32,3.75,3.28,3.04))

处理需求

  1. 基于min列和对应行的lower.limit、upper.limit(假设已通过业务逻辑生成)过滤标记行:
    • 当N=2时,若当前行min落在前1行的上下限区间内,标记该行;
    • 当N=3时,若当前行min落在前2行任意一行的上下限区间内,标记该行;
    • 当N=4时,检查前3行;
    • 当N≥5时,检查前4行。
  2. 对标记出的行,按x分组计算对应的滚动均值。

当前方法计算成本过高,希望找到rollapply实现方式或更高效的方案。


高效实现方案

步骤1:生成上下限(示例逻辑)

假设上下限为min加减固定值,先添加对应列:

DT[, c("lower.limit", "upper.limit") := .(min - 0.2, min + 0.2), by = x]

步骤2:标记符合条件的行

利用data.table的向量化分组操作,结合shift生成前N行的上下限,用between和any判断区间命中:

DT[, marked := fifelse(
  N == 1, FALSE,
  any(between(min, shift(lower.limit, 1:min(N-1,4)), shift(upper.limit, 1:min(N-1,4)))),
  by = x
)]

min(N-1,4)确保只检查最近4行,避免冗余计算。

步骤3:计算标记行的滚动均值

优先使用data.table内置的frollmean(C语言实现,性能远高于rollapply),按x分组计算:

# 以滚动窗口为2为例,可根据需求调整n值
DT[, roll_mean := ifelse(marked, 
                         frollmean(z, n=2, align="right", na.rm=TRUE), 
                         NA_real_), 
   by = x]

rollapply备选实现

如果必须使用zoo包的rollapply,可按分组处理:

library(zoo)
DT[, roll_mean := ifelse(marked,
                         rollapply(z, width=2, FUN=mean, align="right", fill=NA),
                         NA_real_),
   by = x]

注意:rollapply在大数据量下效率远低于data.table的frollmean,仅适合小数据集场景。


内容的提问来源于stack exchange,提问作者zainul abid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:48:31