【问题标题】:Summarising series of 1 and 0 in a dataframe in R在R中的数据框中总结1和0的系列
【发布时间】:2020-02-04 11:30:39
【问题描述】:

我想编写一个 R 代码来总结数据框中的 1 和 0 序列(基本上我需要将运行长度编码应用于列“值”),但我需要保留有关列“ID”的信息.

这是需要总结的数据框示例:

> df
   ID Values
1   1      0
2   2      0
3   3      0
4   4      1
5   5      1
6   6      1
7   7      1
8   8      0
9   9      0
10 10      0
11 11      1
12 12      0
13 13      0
14 14      1
15 15      0
16 16      0

这是预期的输出:

> df
  ID lengths values
1  1       3      0
2  4       4      1
3  8       3      0
4 11       1      1
5 12       2      0
6 14       1      1
7 15       2      0

有人可以帮我高效地写这个吗?

谢谢!

【问题讨论】:

  • 看看rle()

标签: r dataframe run-length-encoding


【解决方案1】:

您可以使用 data.table 的分组和rleid 函数轻松做到这一点:

library(data.table)
setDT(df)
df[, .(ID = ID[1], lengths = .N, values = Values[1]), by = rleid(Values)]
#   rleid ID lengths values
#1:     1  1       3      0
#2:     2  4       4      1
#3:     3  8       3      0
#4:     4 11       1      1
#5:     5 12       2      0
#6:     6 14       1      1
#7:     7 15       2      0

【讨论】:

    【解决方案2】:
    library(tidyverse)
    
    df %>%
      group_by(group = cumsum(Values != lag(Values, default = first(Values)))) %>%  
      summarise(ID = min(ID),
                lengths = n(),
                values = unique(Values)) %>%
      select(-group)
    
    # # A tibble: 7 x 3
    #      ID lengths values
    #   <int>   <int>  <int>
    # 1     1       3      0
    # 2     4       4      1
    # 3     8       3      0
    # 4    11       1      1
    # 5    12       2      0
    # 6    14       1      1
    # 7    15       2      0
    

    【讨论】:

      【解决方案3】:

      这里是一个基于 R 的解决方案:

      r <- rle(df$Values)
      
      data.frame(ID=df$ID[1+cumsum(c(0, head(r$lengths, -1)))], r$lengths, r$values)
      # > data.frame(ID=df$ID[1+cumsum(c(0, head(r$lengths, -1)))], r$lengths, r$values)
      #   ID r.lengths r.values
      # 1  1         3        0
      # 2  4         4        1
      # 3  8         3        0
      # 4 11         1        1
      # 5 12         2        0
      # 6 14         1        1
      # 7 15         2        0
      

      【讨论】:

        【解决方案4】:

        另一个dplyrversion,可能更容易理解:

        df %>%
            mutate(doesValueChange = Values - lag(Values) != 0) %>%
            mutate(doesValueChange = replace_na(doesValueChange, FALSE)) %>%
            mutate(sequenceNr = cumsum(doesValueChange)) %>%
            group_by(sequenceNr) %>%
            summarise(ID = first(ID)
                      , lengths = n()
                      , Values = first(Values))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-12-12
          • 1970-01-01
          • 1970-01-01
          • 2019-04-04
          • 1970-01-01
          • 1970-01-01
          • 2015-01-08
          • 1970-01-01
          相关资源
          最近更新 更多