【问题标题】:Finding values in consecutive rows在连续行中查找值
【发布时间】:2019-01-14 13:55:06
【问题描述】:

下面给出了我的数据框示例。

ID     X      
1      1     
2      2      
3      1      
4      0      
5      0      
6      1      
7      4
8      5 
9      6
10     7
11     0 
12     0

我想对其应用逻辑,以查看 3 个或更多连续行的值是否 >0。如果他们这样做,我想在另一列中标记它们。因此输出将如下所示。

ID     X      Y
1      1      1
2      2      1
3      1      1
4      0      0
5      0      0
6      1      1
7      4      1
8      5      1
9      6      1
10     7      1
11     0      0
12     0      0

扩展 - 如何获得以下输出,为每个组赋予不同的 Y 值?

ID     X      Y
1      1      1
2      2      1
3      1      1
4      0      0
5      0      0
6      1      2
7      4      2
8      5      2
9      6      2
10     7      2
11     0      0
12     0      0

【问题讨论】:

    标签: r for-loop if-statement


    【解决方案1】:

    base R 的一个选项。使用rle查找'X'中大于0的相邻值,然后根据lengthsreplication

    df1$Y <- with(rle(df1$X > 0), as.integer(rep(values & lengths > 2, lengths)))
    df1$Y
    #[1] 1 1 1 0 0 1 1 1 1 1 0 0
    

    对于 OP 帖子中的更新案例

    df1$Y <- inverse.rle(within.list(rle(df1$X > 0), {
                 i1 <- values & (lengths > 2)
          values[i1] <- seq_along(values[i1])}))
    df1$Y
    #[1] 1 1 1 0 0 2 2 2 2 2 0 0
    

    或者使用来自data.tablerleid

    library(data.table)
    setDT(df1)[, Y := as.integer((.N > 2) * (X > 0)),rleid(X > 0)]
    

    数据

    df1 <- structure(list(ID = 1:12, X = c(1L, 2L, 1L, 0L, 0L, 1L, 4L, 5L, 
     6L, 7L, 0L, 0L)), class = "data.frame", row.names = c(NA, -12L
     ))
    

    【讨论】:

      【解决方案2】:

      我们可以使用data.table中的rleid创建组,并在ave中使用,得到每个组的length,并将1分配给长度大于等于3的组。

      library(data.table)
      df$Y <- as.integer(ave(df$X, rleid(df$X > 0), FUN = length) >= 3)
      
      df
      #   ID X Y
      #1   1 1 1
      #2   2 2 1
      #3   3 1 1
      #4   4 0 0
      #5   5 0 0
      #6   6 1 1
      #7   7 4 1
      #8   8 5 1
      #9   9 6 1
      #10 10 7 1
      #11 11 0 0
      #12 12 0 0
      

      编辑

      对于更新后的帖子,我们可以将上述data.table 部分与dplyr 一起添加

      library(dplyr)
      library(data.table)
      
      df %>%
        group_by(group = rleid(X > 0)) %>%
        mutate(Y = ifelse(n() >= 3 & row_number() == 1, 1, 0)) %>%
        ungroup() %>%
        mutate(Y = cumsum(Y) * Y) %>%
        group_by(group) %>%
        mutate(Y = first(Y)) %>%
        ungroup() %>%
        select(-group)
      
      
      #     ID     X     Y
      #   <int> <int> <dbl>
      # 1     1     1     1
      # 2     2     2     1
      # 3     3     1     1
      # 4     4     0     0
      # 5     5     0     0
      # 6     6     1     2
      # 7     7     4     2
      # 8     8     5     2
      # 9     9     6     2
      #10    10     7     2
      #11    11     0     0
      #12    12     0     0
      

      【讨论】:

      • 为什么不去纯粹的data.tabledf[, Y := as.integer(.N &gt;= 3L), by = rleid(X &gt; 0)]
      • @snoram 谢谢,我并没有真正使用data.table,所以我不太了解语法,但data.table 中的某些函数非常方便,例如rleid,因此首选ave .
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 2014-09-04
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多