按组和“时间窗口”计算最大值

4
以下是单位“ID”在“时间”上追踪价值的面板数据:
ID=c(1,1,1,1,1,2,2,2,2,2)
Time=c(1,2,3,4,5,1,2,3,4,5)
Value=c(1,9,4,8,5,2,5,9,7,6)

我想创建一个向量,其中每个“ID”在过去两天内的最大值(假设时间单位为一天)。

输出向量“Max_Value”如下:

Max_Value=c(1,9,9,8,8,2,5,9,9,7)

为了明确,以下是对ID "1"计算Max_Value的方法。
对于ID "1",在“Time=1”时,最大值为1,是{1}的最大值。
类似地,对于ID "1",在“Time 2”时的最大值为9,是{1,9}的最大值。
同样地,对于ID "1",在“Time 3”时的最大值为9,是{9,4}的最大值。
对于ID "1",在“Time 4”时的最大值为8,是{4,8}的最大值。
对于ID "1",在“Time 5”时的最大值为8,是{8,5}的最大值。

你尝试过使用tidyquant包吗? - Santiago I. Hurtado
@SantiagoI.Hurtado 还没有。你能提供一下函数吗? - SSP
这个函数名为tq_transmute。相关说明请参见:https://cran.csiro.au/web/packages/tidyquant/vignettes/TQ02-quant-integrations-in-tidyquant.html。 - Santiago I. Hurtado
4个回答

5
如果你只有向量,而且Time已经完整且排序好了,那么使用slideave可能适合你:
ave(Value, ID, FUN = function(x) slider::slide_dbl(x, max, .before=1))
#> [1] 1 9 9 8 8 2 5 9 9 7

甚至可以使用完整的基础 R 解决方案:

Value[ave(Value, ID, FUN = function(x) c(0, -(diff(x)<0))) + seq_along(Value)]
#> [1] 1 9 9 8 8 2 5 9 9 7

否则,您可以使用 dplyr + slider 来解决它:
library(dplyr)
data.frame(ID, Time, Value) %>% 
 group_by(ID) %>% 
 mutate(Max_Value = slider::slide_index_dbl(Value, Time, max, .before=1)) %>% 
 ungroup()

#> # A tibble: 10 x 4
#>       ID  Time Value Max_Value
#>    <dbl> <dbl> <dbl>     <dbl>
#>  1     1     1     1         1
#>  2     1     2     9         9
#>  3     1     3     4         9
#>  4     1     4     8         8
#>  5     1     5     5         8
#>  6     2     1     2         2
#>  7     2     2     5         5
#>  8     2     3     9         9
#>  9     2     4     7         9
#> 10     2     5     6         7

2

试试这个:

library(data.table)
dt <- data.table(ID=c(1,1,1,1,1,2,2,2,2,2),
                 Time=c(1,2,3,4,5,1,2,3,4,5),
                 Value=c(1,9,4,8,5,2,5,9,7,6))

max_v <- function(x) max(dt[ID==x$ID & Time <= x$Time & Time > (x$Time-2) ,Value])

sapply(split(dt,1:nrow(dt)),max_v)

2

我相信你可以使用来自zoorollapply()风格函数,设置宽度为2:

library(dplyr)
library(tidyr)
library(zoo)
#Data
df <- data.frame(ID,Time,Value)
#Code
newdf <- df %>% group_by(ID) %>%
  mutate(Max=rollapply(Value,width=2,FUN=function(x) max(x, na.rm=TRUE),
                       by=1, by.column=TRUE,partial=TRUE,fill=NA, align="right"))

输出:

# A tibble: 10 x 4
# Groups:   ID [2]
      ID  Time Value   Max
   <dbl> <dbl> <dbl> <dbl>
 1     1     1     1     1
 2     1     2     9     9
 3     1     3     4     9
 4     1     4     8     8
 5     1     5     5     8
 6     2     1     2     2
 7     2     2     5     5
 8     2     3     9     9
 9     2     4     7     9
10     2     5     6     7

谢谢你的回答!我想把窗口长度从“过去两天”改为“过去30天”,应该怎么设置?只需要将“width=2”替换为“width=30”吗? - SSP
@SSP 是的,你说得对,将窗口宽度设置为30。那非常正确 :) 如果不清楚,请告诉我! - Duck

2

使用 data.table,您还可以尝试 frollapply(快速滚动函数)。请注意,在仅有一个元素可用的 ID 组的初始行中,fill 被设置为 first(Value),而不是两个。

dt <- data.frame(ID,Time,Value)

setDT(dt)

dt[, ValueMax := frollapply(x = Value, 
                            n = 2, 
                            max, 
                            fill = first(Value), 
                            align = "right", 
                            na.rm = TRUE), 
   by = ID]

输出

    ID Time Value ValueMax
 1:  1    1     1        1
 2:  1    2     9        9
 3:  1    3     4        9
 4:  1    4     8        8
 5:  1    5     5        8
 6:  2    1     2        2
 7:  2    2     5        5
 8:  2    3     9        9
 9:  2    4     7        9
10:  2    5     6        7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接