【问题标题】:How to detect consecutive values above a threshold?如何检测高于阈值的连续值?
【发布时间】:2019-02-27 05:07:34
【问题描述】:

我想对数据应用滚动函数来检测值在哪个点大于特定阈值。

library(tidyverse)

df <- tibble(
  x = 1:10,
  y = c(1, 3, 4, 1, 5, 34, 43, 1, 45, 3)
)

df
#> # A tibble: 10 x 2
#>        x     y
#>    <int> <dbl>
#>  1     1     1
#>  2     2     3
#>  3     3     4
#>  4     4     1
#>  5     5     5
#>  6     6    34
#>  7     7    43
#>  8     8     1
#>  9     9    45
#> 10    10     3

我想要找到接下来 2 个值高于某个阈值(比如 30)的行。这将产生:

tibble(
  x = 1:10,
  y = c(1, 3, 4, 1, 5, 34, 43, 1, 45, 3),
  i = c(FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE)
)
#> # A tibble: 10 x 3
#>        x     y i    
#>    <int> <dbl> <lgl>
#>  1     1     1 FALSE
#>  2     2     3 FALSE
#>  3     3     4 FALSE
#>  4     4     1 FALSE
#>  5     5     5 FALSE
#>  6     6    34 TRUE 
#>  7     7    43 FALSE
#>  8     8     1 FALSE
#>  9     9    45 FALSE
#> 10    10     3 FALSE

我有一个大型数据集(几百万行),因此我正在尝试找到一个有效的解决方案。也许使用data.tablereprex package (v0.2.1) 于 2019 年 2 月 26 日创建

【问题讨论】:

    标签: r


    【解决方案1】:

    1) 使用rollapply 滚动每个连续对,检查它们是否都高于阈值:

    library(dplyr)
    library(zoo)
    
    df %>% mutate(i = rollapply(y > 30, 2, all, align = "left", fill = FALSE))
    
    # A tibble: 10 x 3
           x     y i    
       <int> <dbl> <lgl>
     1     1     1 FALSE
     2     2     3 FALSE
     3     3     4 FALSE
     4     4     1 FALSE
     5     5     5 FALSE
     6     6    34 TRUE 
     7     7    43 FALSE
     8     8     1 FALSE
     9     9    45 FALSE
    10    10     3 FALSE
    

    2) 另一种方法是使用lead

    df %>% mutate(i = y > 30 & lead(y) > 30)
    

    【讨论】:

    • 如果最后两个值高于阈值,可能lead(y, default = FALSE) 以避免将最后一个值设置为NA
    【解决方案2】:

    data.table 来自@G 的 tidyverse 版本。格洛腾迪克:

    dt <- as.data.table(df)
    
    thresh <- 30
    
    dt[, i := y > thresh & shift(y, -1L, fill = FALSE) > thresh][]
    
         x  y     i
     1:  1  1 FALSE
     2:  2  3 FALSE
     3:  3  4 FALSE
     4:  4  1 FALSE
     5:  5  5 FALSE
     6:  6 34  TRUE
     7:  7 43 FALSE
     8:  8  1 FALSE
     9:  9 45 FALSE
    10: 10  3 FALSE
    

    感谢@Henrik 为i 提供了更短的表达式。我需要更新data.table 才能使用它(旧版本没有为n 参数取负值)

    【讨论】:

    • 或略短:i := y &gt; thresh &amp; shift(y, -1L, fill = FALSE) &gt; thresh
    • 是否可以验证前 2 个观察值是否低于阈值?
    • 是的,使用i := y &gt; thresh &amp; shift(y, -1L, fill = FALSE) &amp; shift(y, -2L, fill = FALSE) 应该这样做
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 2021-01-04
    • 2017-06-01
    • 2019-11-13
    • 2021-11-21
    • 1970-01-01
    相关资源
    最近更新 更多