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

在R data.table中按x分组、基于y计算z的滚动平均值

问题描述

现有如下R data.table数据:

library(data.table)
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 = c(1,2,3,4,4,4,4,4,1,2,3,4,4,4,4,4), 
  z = c(53,71,27,64,43,62,61,85,44,56,23,37,31,48,80,38)
)

需要新增Roll Mean列,计算规则为:在每个x分组内,

  • 当y=1时,Roll Mean为NA;
  • 当y=2时,取前1个z值的均值;
  • 当y=3时,取前2个z值的均值;
  • 当y=4时,第一个y=4的行取前3个z值的均值,后续y=4的行取前4个z值的均值。

预期输出如下:

N   x   y   z   Roll Mean 
1   11  1   53  NA
2   11  2   71  53
3   11  3   27  62
4   11  4   64  50.33333333
5   11  4   43  53.75
6   11  4   62  51.25
7   11  4   61  49
8   11  4   85  57.5
9   21  1   44  NA
10  21  2   56  44
11  21  3   23  50
12  21  4   37  41
13  21  4   31  40
14  21  4   48  36.75
15  21  4   80  34.75
16  21  4   38  49

当前使用固定窗口的滚动均值代码,结果不符合预期:

DT[, RollingAvg := frollapply(z,4, mean), .(x)] 
解决方案

原代码的问题在于使用了固定大小为4的滚动窗口,无法满足需求中动态变化的窗口规则。可以通过在x分组内标记y=4的行序号,再结合嵌套的fifelse实现动态窗口计算:

library(data.table)

DT[, `Roll Mean` := {
  # 给每个x分组内的y=4行标记序号,第一个y=4为1,依次递增
  y4_seq <- cumsum(y == 4)
  # 根据规则分情况计算
  fifelse(y == 1, NA_real_,
          fifelse(y == 2, shift(z, 1),
                  fifelse(y == 3, (shift(z, 1) + shift(z, 2)) / 2,
                          fifelse(y4_seq == 1, (shift(z, 1) + shift(z, 2) + shift(z, 3)) / 3,
                                  (shift(z, 1) + shift(z, 2) + shift(z, 3) + shift(z, 4)) / 4))))
}, by = x]

# 查看结果
print(DT)

代码解释

  1. 分组内标记y=4的行:使用cumsum(y == 4)在每个x分组内为y=4的行生成递增序号,区分第一个和后续的y=4行。
  2. 分条件计算:
    • y=1:直接返回NA_real_(确保数值类型统一)
    • y=2:用shift(z,1)取前1行的z值(单个值的均值即自身)
    • y=3:取前2行的z值求和后除以2
    • 第一个y=4行:取前3行的z值求和后除以3
    • 后续y=4行:取前4行的z值求和后除以4

运行上述代码后,即可得到符合预期的Roll Mean列。

内容的提问来源于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.21 20:06:23