【问题标题】:find the first value multiple times in a time series in R在R中的时间序列中多次找到第一个值
【发布时间】:2021-11-22 04:27:34
【问题描述】:

我正在尝试在时间序列中多次查找特定值,在本例中是第一个值。数据是这样的

data <- data.table::data.table(value = c(0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1),
                               time  = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21))

现在我想找到value == 1 的第一个值并给我时间。 时间的结果应该如下所示:4、14、18

如果解决方案灵活,那么您可以跳过少量后面的零,这也会有很大帮助。 对于这种情况,时间的结果将如下所示:4、18,因为您可以跳过中间的 2 个零。

我已经尝试过使用 which(min) 的解决方案,但它只给了我第一个值,而不是下面的第一个值。

【问题讨论】:

    标签: r time-series data.table


    【解决方案1】:

    您需要为每个连续的 0&1 运行创建一个组。然后您可以按此分组并取第一行。

    data %>%
      mutate(group = cumsum(value  != lag(value , 1, TRUE))) %>%
      group_by(group) %>%
      filter(row_number()==1, value == 1) %>%
      select(-group)
    

    【讨论】:

      【解决方案2】:

      使用data.table rleid -

      data$time[!duplicated(data.table::rleid(data$value)) & data$value == 1]
      #[1]  4 14 18
      

      如果你想跳过一些连续的零计数,你可以使用这个函数。

      skip_zero <- function(df, n = 0) {
        inds <- data.table::rleid(df$value)
        df$value[ave(inds, inds, FUN = length)  <= n & df$value == 0] <- 1
        inds <- data.table::rleid(df$value)
        df$time[!duplicated(inds) & df$value == 1]
      }
      
      skip_zero(data)
      #[1]  4 14 18
      
      skip_zero(data, 2)
      #[1]  4 14
      

      【讨论】:

      • 我尝试了您的解决方案,因为我喜欢 data.table 的方式。如果不仅有我想忽略的零而且还有 3、4、5 等...并且我要查找的值不是 1 而是 4,我必须更改什么?
      • 将第二行从df$value == 0更改为df$value %in% c(0, 3, 4, 5),将最后一行df$value == 1更改为df$valie == 4
      • 非常感谢,很好的解决方案!我的真实数据出错了,所以现在可以使用了。
      【解决方案3】:
      with(
        rle(data$value),
        c(1, 1 + cumsum(lengths))[which(values == 1)]
      )
      # [1]  4 14 18
      

      【讨论】:

        【解决方案4】:

        OP 提到 in a comment 他/她喜欢 data.table 方式

        所以,这是一个 方法,它使用 shift()joinvalue 列中查找 子序列 的出现:

        library(data.table)
        data[, shift(value, 1:0)][.(0, 1), on = .(V1, V2), which = TRUE]
        
        [1]  4 14 18
        

        在这里,我们在value 中查找子序列(0, 1) 的出现。这可以很容易地扩展到覆盖任意子序列,例如,

        data[, shift(value, 3:0)][.(0, 0, 0, 1), on = .(V1, V2, V3, V4), which = TRUE]
        
        [1]  4 14
        

        跳过两个后续零的出现。

        说明

        待完成

        扩展

        通用函数待完成

        【讨论】:

          猜你喜欢
          • 2021-12-05
          • 1970-01-01
          • 1970-01-01
          • 2021-07-27
          • 2022-12-14
          • 2020-12-30
          • 2018-03-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多