Zoo::Rollmax 如何缩短宽度以防止错误

Zoo::Rollmax How to shorten width to prevent errors

我有 10 天的值,对于每一天,我都想知道前 4 天的最大值。如果没有 4 天的价值,那么我想要最近 3 天的最大值,等等。代码示例:

set.seed(131)
Index <- 1:10
Val <- c(sample(10, 10, replace = T))
df = data.frame(Index, Val)

dfoo = df %>%
  mutate(Lag1 = lag(Val, 1, default = 0), #get last days value
         Last4Max = rollmax(Lag1, 4, partial = T, fill = 0, align = "right")) #get max of last 4 days

这适用于除第 2/3 天以外的所有人,因为 Lag1 中没有 4 个值(第 1 天应该是 0/NA,因为没有 "previous" 天)。

   Index Val Lag1    Last4Max
1      1   3    0        0
2      2   2    3        0
3      3   3    2        0
4      4   4    3        3
5      5   9    4        4
6      6   6    9        9
7      7   6    6        9
8      8   3    6        9
9      9   4    3        9
10    10  10    4        6

所以 Last4Max 对于索引 2/3 应该是 3,对于 1 应该是 0/NA。有没有办法改变宽度大小来考虑宽度>行数?我的替代方法是为每个滞后创建 4 个变量(默认值 = 0),然后取所有 4 个中的最大值。我知道这会起作用,但它看起来很笨重,如果我想快速做最后一个最大值,它会限制我更大数据集上的 10 天。

谢谢

1) 注意:

  • 根据 ?rollmax 它没有 partial 参数;但是,我们可以使用带有 partial 参数的 rollapplyrollapplyr 并指定 FUN = max
  • rollapplyr(还有 rollmaxr)在末尾带有 r 默认为 align = "right" 允许避免写出该参数
  • width 参数可以指定偏移量的一个组成部分列表,以便指定要使用的前 4 个元素,我们可以指定 width = list(-seq(4)) 消除对单独滞后列的需要。

将所有这些放在一起我们得到:

rollapplyr(Val, list(-seq(4)), max, partial = TRUE, fill = 0)
## [1] 0 3 3 3 4 9 9 9 9 6

2) 另一种方法是使用宽度 5 但在取最大值时不使用最后一个元素。在这种情况下,我们不需要 fill = 0,因为它能够处理 Val 的每个组件,无需填写任何内容。

Max <- function(x) if (length(x) > 1) max(head(x, -1)) else 0
rollapplyr(Val, 5, Max, partial = TRUE)

2a) 如果我们知道 Val 的所有元素都是非负的,那么我们可以交替使用 Max 的这个较短的定义:

Max <- function(x) max(head(x, -1), 0)