如何使用 R 中的 apply family 计算 5 天累计
how to calculate 5 days cumulative using apply family in R
我有一个矩阵数据框 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)
}
}
我想知道apply系列中有没有函数可以做同样的事情,因为这段代码很耗时。
例如,如果我使用命令
生成数据框
ens <- matrix(rnorm(200),20)
我一次要5行的累加和。即 row1:row5、row2:row6、row3:row7 等数据框形式的总和。
我试过以这种形式使用应用函数:
apply(apply(apply(apply( apply(m, 2, cumsum),2, cumsum), 2, cumsum),2,cumsum),2,cumsum)
但问题是我没有获得以 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
这可能需要根据您希望如何处理少于 5 个值的 windows 进行调整(例如,在开头)。
另一种不太复杂的方法:创建 5 个变量并由变量求和 5 次。
这里:
m <- data.table(matrix(1:48, ncol = 4))
m[, index := .I]
m[, i1 := floor((index - 1) / 5) * 5 + 1]
m[, i2 := floor((index - 2) / 5) * 5 + 2]
m[, i3 := floor((index - 3) / 5) * 5 + 3]
m[, i4 := floor((index - 4) / 5) * 5 + 4]
m[, i5 := floor((index - 5) / 5) * 5 + 5]
cumsumm <- rbindlist(list(m[, list(value = sum(V1)), by = "i1"]
, m[, list(value = sum(V1)), by = "i2"]
, m[, list(value = sum(V1)), by = "i3"]
, m[, list(value = sum(V1)), by = "i4"]
, m[, list(value = sum(V1)), by = "i5"]), use.names=F)[i1 > 0, ]
另一种选择是roll_sum
(数据来自@Rolandpost)
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
正如@alexis_laz在评论中提到的,roll_sumr
也可以采用矩阵。效率更高。
roll_sumr(m, 5, by = 1)
基准
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
我有一个矩阵数据框 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)
}
}
我想知道apply系列中有没有函数可以做同样的事情,因为这段代码很耗时。
例如,如果我使用命令
生成数据框 ens <- matrix(rnorm(200),20)
我一次要5行的累加和。即 row1:row5、row2:row6、row3:row7 等数据框形式的总和。
我试过以这种形式使用应用函数:
apply(apply(apply(apply( apply(m, 2, cumsum),2, cumsum), 2, cumsum),2,cumsum),2,cumsum)
但问题是我没有获得以 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
这可能需要根据您希望如何处理少于 5 个值的 windows 进行调整(例如,在开头)。
另一种不太复杂的方法:创建 5 个变量并由变量求和 5 次。 这里:
m <- data.table(matrix(1:48, ncol = 4))
m[, index := .I]
m[, i1 := floor((index - 1) / 5) * 5 + 1]
m[, i2 := floor((index - 2) / 5) * 5 + 2]
m[, i3 := floor((index - 3) / 5) * 5 + 3]
m[, i4 := floor((index - 4) / 5) * 5 + 4]
m[, i5 := floor((index - 5) / 5) * 5 + 5]
cumsumm <- rbindlist(list(m[, list(value = sum(V1)), by = "i1"]
, m[, list(value = sum(V1)), by = "i2"]
, m[, list(value = sum(V1)), by = "i3"]
, m[, list(value = sum(V1)), by = "i4"]
, m[, list(value = sum(V1)), by = "i5"]), use.names=F)[i1 > 0, ]
另一种选择是roll_sum
(数据来自@Rolandpost)
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
正如@alexis_laz在评论中提到的,roll_sumr
也可以采用矩阵。效率更高。
roll_sumr(m, 5, by = 1)
基准
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