计算事件发生后的观察次数
Calculating the Number of Observations Since an Event Occurred
我有以下温度矢量(以 ˚C 为单位):
Temperature <- c(-3:3, 3:-3, rep(-3, 2), -2:-1, 1:3, 2:1, -1:-4)
我需要计算自上次冻结事件以来经过的时间(观察次数),我还需要计算自上次解冻事件以来经过的观察次数。冻结事件的标志是温度从正值到负值的转变,解冻事件的标志是温度从负值到正值的转变。输出应该类似于这些向量:
Time_Since_Last_Freeze <- c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3)
Time_Since_Last_Thaw <- c(NA, NA, NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8)
我在 Stack Overflow 上看到过一些类似的问题,但其中 none 正是我所需要的。生成这两个输出向量的有效方法是什么?
你可以使用这个函数,它基本上检查原始向量中冻结和解冻的索引,然后计算在每个冻结或解冻时刻之间应用一系列长度为 dif
的连续数:
f <- function(temp, freeze){
if(freeze)
idx <- which(temp <= 0 & dplyr::lag(temp) > 0)
else
idx <- which(temp >= 0 & dplyr::lag(temp) < 0)
diff <- diff(c(idx, length(temp) + 1))
vec <- rep(NA, length(temp))
vec[min(idx):length(temp)] <- unlist(sapply(diff, \(x) seq_len(x) - 1))
vec
}
输出
f(Temperature, freeze = TRUE)
[1] NA NA NA NA NA NA NA NA NA NA 0 1 2 3 4 5 6 7 8 9 10 11 12 0 1 2 3
f(Temperature, freeze = FALSE)
[1] NA NA NA 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 1 2 3 4 5 6 7 8
不是您想要的输出,尽管您可能会在 cgwtools
:
中发现有用的内容
temp <- c(-3:3, 3:-3, rep(-3, 2), -2:3, 2:-4)
which(temp > 0)
[1] 5 6 7 8 9 10 20 21 22 23 24
cgwtools::seqle(which(temp > 0))
Run Length Encoding
lengths: int [1:2] 6 5
values : int [1:2] 5 20
> cgwtools::seqle(which(temp <= 0))
Run Length Encoding
lengths: int [1:3] 4 9 5
values : int [1:3] 1 11 25
通过总结的方式
另一种可能的解决方案是在将 Temperature
转换为数据帧后使用 tidyverse
:
library(tidyverse)
library(rlang)
reduce(list(data.frame(Temperature), "thaw", "freeze"), \(y, x) y %>%
mutate(!!x := if (x == "thaw")
ifelse(lag(Temperature < 0) & Temperature >= 0, row_number(), NA ) else
ifelse(lag(Temperature > 0) & Temperature <= 0, row_number(), NA )) %>%
fill(all_of(x)) %>%
group_by(!!parse_expr(x)) %>%
mutate(!!x := ifelse(is.na(!!parse_expr(x)), NA, row_number()-1)) %>%
ungroup)
#> # A tibble: 27 x 3
#> Temperature thaw freeze
#> <dbl> <dbl> <dbl>
#> 1 -3 NA NA
#> 2 -2 NA NA
#> 3 -1 NA NA
#> 4 0 0 NA
#> 5 1 1 NA
#> 6 2 2 NA
#> 7 3 3 NA
#> 8 3 4 NA
#> 9 2 5 NA
#> 10 1 6 NA
#> # ... with 17 more rows
我有以下温度矢量(以 ˚C 为单位):
Temperature <- c(-3:3, 3:-3, rep(-3, 2), -2:-1, 1:3, 2:1, -1:-4)
我需要计算自上次冻结事件以来经过的时间(观察次数),我还需要计算自上次解冻事件以来经过的观察次数。冻结事件的标志是温度从正值到负值的转变,解冻事件的标志是温度从负值到正值的转变。输出应该类似于这些向量:
Time_Since_Last_Freeze <- c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3)
Time_Since_Last_Thaw <- c(NA, NA, NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8)
我在 Stack Overflow 上看到过一些类似的问题,但其中 none 正是我所需要的。生成这两个输出向量的有效方法是什么?
你可以使用这个函数,它基本上检查原始向量中冻结和解冻的索引,然后计算在每个冻结或解冻时刻之间应用一系列长度为 dif
的连续数:
f <- function(temp, freeze){
if(freeze)
idx <- which(temp <= 0 & dplyr::lag(temp) > 0)
else
idx <- which(temp >= 0 & dplyr::lag(temp) < 0)
diff <- diff(c(idx, length(temp) + 1))
vec <- rep(NA, length(temp))
vec[min(idx):length(temp)] <- unlist(sapply(diff, \(x) seq_len(x) - 1))
vec
}
输出
f(Temperature, freeze = TRUE)
[1] NA NA NA NA NA NA NA NA NA NA 0 1 2 3 4 5 6 7 8 9 10 11 12 0 1 2 3
f(Temperature, freeze = FALSE)
[1] NA NA NA 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 1 2 3 4 5 6 7 8
不是您想要的输出,尽管您可能会在 cgwtools
:
temp <- c(-3:3, 3:-3, rep(-3, 2), -2:3, 2:-4)
which(temp > 0)
[1] 5 6 7 8 9 10 20 21 22 23 24
cgwtools::seqle(which(temp > 0))
Run Length Encoding
lengths: int [1:2] 6 5
values : int [1:2] 5 20
> cgwtools::seqle(which(temp <= 0))
Run Length Encoding
lengths: int [1:3] 4 9 5
values : int [1:3] 1 11 25
通过总结的方式
另一种可能的解决方案是在将 Temperature
转换为数据帧后使用 tidyverse
:
library(tidyverse)
library(rlang)
reduce(list(data.frame(Temperature), "thaw", "freeze"), \(y, x) y %>%
mutate(!!x := if (x == "thaw")
ifelse(lag(Temperature < 0) & Temperature >= 0, row_number(), NA ) else
ifelse(lag(Temperature > 0) & Temperature <= 0, row_number(), NA )) %>%
fill(all_of(x)) %>%
group_by(!!parse_expr(x)) %>%
mutate(!!x := ifelse(is.na(!!parse_expr(x)), NA, row_number()-1)) %>%
ungroup)
#> # A tibble: 27 x 3
#> Temperature thaw freeze
#> <dbl> <dbl> <dbl>
#> 1 -3 NA NA
#> 2 -2 NA NA
#> 3 -1 NA NA
#> 4 0 0 NA
#> 5 1 1 NA
#> 6 2 2 NA
#> 7 3 3 NA
#> 8 3 4 NA
#> 9 2 5 NA
#> 10 1 6 NA
#> # ... with 17 more rows