【问题标题】:Increment by 1 for every change in column列中的每次更改增加 1
【发布时间】:2015-04-15 21:28:43
【问题描述】:

假设我有以下数据框

set.seed(123)
df <- data.frame(var1=(runif(10)>0.5)*1)

var1 可以有任何类型/数量的级别,而不是特别是 0 和 1s

我想创建一个var2,每次var1 更改没有使用for loop

这种情况下的预期结果是:

data.frame(var1=(runif(10)>0.5)*1, var2=c(1, 2, 3, 4, 4, 5, 6, 6, 6, 7))

var1 var2
   0    1
   1    2
   0    3
   1    4
   1    4
   0    5
   1    6
   1    6
   1    6
   0    7

数据框的另一个选项可能是:

df <- data.frame(var1=c("a", "a", "1", "0", "b", "b", "b", "c", "1", "1"))

在这种情况下,结果应该是:

var1 var2
   a    1
   a    1
   1    2
   0    3
   b    4
   b    4
   b    4
   c    5
   1    6
   1    6

【问题讨论】:

    标签: r


    【解决方案1】:

    以弗利克先生的回答为基础:

    df$var2 <- cumsum(c(0,as.numeric(diff(df$var1))!=0))
    

    但是如果你不想使用diff你仍然可以使用:

    df$var2 <- c(0,cumsum(as.numeric(with(df,var1[1:(length(var1)-1)] != var1[2:length(var1)]))))
    

    它从 0 开始,而不是从 1 开始,但我相信您会知道如何更改它,如果您愿意的话。

    【讨论】:

    • 谢谢,这正是我想要的。
    • 这似乎在使用分组 tibble 时中断。
    【解决方案2】:

    如何使用diff()cumsum()。例如

    df$var2 <- cumsum(c(1,diff(df$var1)!=0))
    

    【讨论】:

    • var1 的级别可以是不只是 0 和或 1 的任何值。例如 c("a", "a", "1", "0", "b", "b", "a", ....)
    • 我收到了Warning message: In is.na(r) : is.na() applied to non-(list or vector) of type 'NULL'
    • 你需要使用as.numeric(diff(df$var1))==0 而不是单独使用 diff()
    【解决方案3】:

    这些看起来像游程编码 (rle)

    x = c("a", "a", "1", "0", "b", "b", "b", "c", "1", "1")
    r = rle(x)
    

    > rle(x)
    Run Length Encoding
      lengths: int [1:6] 2 1 1 3 1 2
      values : chr [1:6] "a" "1" "0" "b" "c" "1"
    

    这表示第一个值(“a”)连续出现 2 次,然后“1”出现一次,依此类推。您所追求的是沿着“长度”创建一个序列,并复制每个元素元素出现次数的顺序,所以

    > rep(seq_along(r$lengths), r$lengths)
     [1] 1 1 2 3 4 4 4 5 6 6
    

    其他答案是半欺骗性的,因为它们依赖于作为 factor() 的列;当列实际上是一个字符()时,它们会失败。

    > diff(x)
    Error in r[i1] - r[-length(r):-(length(r) - lag + 1L)] : 
      non-numeric argument to binary operator
    

    一种解决方法是将字符映射为整数,沿线

    > diff(match(x, x))
    [1]  0  2  1  1  0  0  3 -5  0
    

    嗯,不过话说回来我发现 rle 对因子不起作用!

    > f = factor(x)
    > rle(f)
    Error in rle(factor(x)) : 'x' must be a vector of an atomic type
    > rle(as.vector(f))
    Run Length Encoding
      lengths: int [1:6] 2 1 1 3 1 2
      values : chr [1:6] "a" "1" "0" "b" "c" "1"
    

    【讨论】:

      【解决方案4】:

      这是另一个使用inverse.rle() 的基于 R 的解决方案:

      df <- data.frame(var1=c("a", "a", "1", "0", "b", "b", "b", "c", "1", "1"))
      r <- rle(as.character(df$var1))
      r$values <- seq_along(r$values)
      df$var2 <- inverse.rle(r)
      

      短版:

      df$var2 <- with(rle(as.character(df$var1)), rep(seq_along(values), lengths))
      

      这是data.table的解决方案:

      library("data.table")
      dt <- data.table(var1=c("a", "a", "1", "0", "b", "b", "b", "c", "1", "1"))
      dt[, var2:=rleid(var1)]
      

      【讨论】:

        【解决方案5】:

        我只是复制上面 Martin Morgan 的 rle() 答案,但使用 tidyverse 约定来实现它,以便将分组列直接添加到数据框/小标题中,这是我大部分时间最终使用的方式。

        ## Using run-length-encoding, create groups of identical values and put that
        ## common grouping identifier into a `grp` column.
        library(tidyverse)
        
        set.seed(42)
        
        df <- tibble(x = sample(c(0,1), size=20, replace=TRUE, prob = c(0.2, 0.8)))
        
        df %>%
            mutate(grp = rle(x)$lengths %>% {rep(seq(length(.)), .)})
        #> # A tibble: 20 x 2
        #>        x   grp
        #>    <dbl> <int>
        #>  1     0     1
        #>  2     0     1
        #>  3     1     2
        #>  4     0     3
        #>  5     1     4
        #>  6     1     4
        #>  7     1     4
        #>  8     1     4
        #>  9     1     4
        #> 10     1     4
        #> 11     1     4
        #> 12     1     4
        #> 13     0     5
        #> 14     1     6
        #> 15     1     6
        #> 16     0     7
        #> 17     0     7
        #> 18     1     8
        #> 19     1     8
        #> 20     1     8
        

        【讨论】:

          猜你喜欢
          • 2017-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-04
          • 2020-03-14
          • 2019-04-14
          • 2021-09-30
          • 2019-10-21
          相关资源
          最近更新 更多