按组和时间计算最大值"window"

Compute the maximum value by group and by a time "window"

对于以下面板数据(跟踪单元“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”,“时间=1”的最大值为1,即最大{1}。

同理,对于ID“1”,“时间2”处的最大值为9,即最大值为{1,9}。

同样,对于ID“1”,“时间3”处的最大值为9,即最大值为{9,4}。

对于ID“1”,“时间4”处的最大值为8,即最大值为{4,8}。

对于ID“1”,“时间5”处的最大值为8,即最大值为{8,5}。

试试这个:

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)

我相信您可以使用 zoo 中的 rollapply() 样式函数,将宽度设置为 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

如果您只有向量并且 Time 是完整的和排序的,slide + ave 可能适合您:

ave(Value, ID, FUN = function(x) slider::slide_dbl(x, max, .before=1))
#> [1] 1 9 9 8 8 2 5 9 9 7

甚至是完整的 Base 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

有了data.table你也可以试试frollapply(快速滚动功能)。请注意,fillID 组的初始行中设置为 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