如何使用R中的apply family计算累计5天

sau*_*abh 1 statistics for-loop r apply lapply

我有一个矩阵数据框6940行和100列.我需要在数据集上一次累积5天.现在我能够为此构建一个for循环代码,如下所示:

cum<- matrix(data=q1,nrow=6940,ncol=100)
for (j in 1:100){
  for (i in 1:6940){
    cum[i,j]<-sum(q1[i,j],q1[i+1,j],q1[i+2,j],q1[i+3,j],q1[i+4,j],na.rm=T)
  }
}
Run Code Online (Sandbox Code Playgroud)

我想知道应用系列中是否有任何功能来执行相同操作,因为此代码非常耗时.

例如,如果我使用该命令生成数据帧

 ens <- matrix(rnorm(200),20)
Run Code Online (Sandbox Code Playgroud)

我想要一次累计5行.即数据帧形式的row1:row5,row2:row6,row3:row7等的总和.

我试过在这种形式下使用apply函数:

apply(apply(apply(apply( apply(m, 2, cumsum),2, cumsum), 2, cumsum),2,cumsum),2,cumsum)
Run Code Online (Sandbox Code Playgroud)

但问题是我没有得到累积的5块,只有一个整体累积.

Rol*_*and 5

以下是使用stats::filter函数计算滚动总和并apply循环列的一种方法:

m <- matrix(1:48, ncol = 4)
#      [,1] [,2] [,3] [,4]
# [1,]    1   13   25   37
# [2,]    2   14   26   38
# [3,]    3   15   27   39
# [4,]    4   16   28   40
# [5,]    5   17   29   41
# [6,]    6   18   30   42
# [7,]    7   19   31   43
# [8,]    8   20   32   44
# [9,]    9   21   33   45
#[10,]   10   22   34   46
#[11,]   11   23   35   47
#[12,]   12   24   36   48

apply(m, 2, filter, filter = rep(1, 5), sides = 1)
#      [,1] [,2] [,3] [,4]
# [1,]   NA   NA   NA   NA
# [2,]   NA   NA   NA   NA
# [3,]   NA   NA   NA   NA
# [4,]   NA   NA   NA   NA
# [5,]   15   75  135  195
# [6,]   20   80  140  200
# [7,]   25   85  145  205
# [8,]   30   90  150  210
# [9,]   35   95  155  215
#[10,]   40  100  160  220
#[11,]   45  105  165  225
#[12,]   50  110  170  230
Run Code Online (Sandbox Code Playgroud)

这可能需要根据您想要处理少于5个值的窗口的方式进行调整(例如,在此处开头).


akr*_*run 5

另一种选择是roll_sum(来自@Roland 帖子的数据)

library(RcppRoll)
apply(m, 2, roll_sumr, 5)
#       [,1] [,2] [,3] [,4]
# [1,]   NA   NA   NA   NA
# [2,]   NA   NA   NA   NA
# [3,]   NA   NA   NA   NA
# [4,]   NA   NA   NA   NA
# [5,]   15   75  135  195
# [6,]   20   80  140  200
# [7,]   25   85  145  205
# [8,]   30   90  150  210
# [9,]   35   95  155  215
#[10,]   40  100  160  220
#[11,]   45  105  165  225
#[12,]   50  110  170  230
Run Code Online (Sandbox Code Playgroud)

正如评论中提到的@alexis_laz,roll_sumr也可以采用矩阵。它更有效率。

roll_sumr(m, 5, by = 1)
Run Code Online (Sandbox Code Playgroud)

基准

set.seed(24)
m1 <- matrix(sample(1:50, 5000*5000, replace=TRUE), ncol=5000)
system.time(apply(m1, 2, roll_sumr, 5))
# user  system elapsed 
# 1.84    0.16    1.99 

system.time(roll_sumr(m1, 5, by = 1))
#  user  system elapsed 
#  0.59    0.15    0.74 

system.time(apply(m1, 2, stats::filter, filter = rep(1, 5), sides = 1))
#  user  system elapsed 
#  4.46    0.20    4.68 
Run Code Online (Sandbox Code Playgroud)