按组和时间计算最大值"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
(快速滚动功能)。请注意,fill
在 ID
组的初始行中设置为 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
对于以下面板数据(跟踪单元“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
(快速滚动功能)。请注意,fill
在 ID
组的初始行中设置为 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