r - 计算自事件发生以来的观察次数

我有以下 vector 温度(以°C为单位):

Temperature <- c(-3:3, 3:-3, rep(-3, 2), -2:-1, 1:3, 2:1, -1:-4)

我需要计算自上次冻结事件以来经过的时间(观察次数),我还需要计算自上次解冻事件以来经过的观察次数。冻结事件的标志是温度从正到负 values 的转变,而解冻事件的标志是温度从负到正的转变 values。输出应该类似于这些 vectors:

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 上看到过一些类似的问题,但没有一个是我真正需要的。生成这两个输出 vectors 的有效方法是什么?

回答1

您可以使用这个函数,它基本上检查原始 vector 中的冻结和解冻索引,然后计算在每个冻结或解冻时刻之间应用一系列连续长度的 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

回答2

不是您想要的输出,尽管您可能会在 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

以总结的方式。

回答3

另一种可能的解决方案是在将 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++ - 用户自定义推导与工厂函数

在编写像下面的FooWrapper<WrappeeT>这样的通用包装类模板时,在创建包装类的实例时推断WrappeeT很方便。例如,只需键入wrap(foo)而不是键入wrap<Foo>(foo)。实...