【问题标题】:Generate counts within group and subgroup在组和子组内生成计数
【发布时间】:2020-02-06 12:16:31
【问题描述】:

我想创建一个列来计算事件连续发生的次数。想象一下抛硬币 100 次,然后计算连续出现的正面(“H”)和故事(“T”)的数量:

结果: "H","H","H","H","T","T","T","H","T","T",...

计数: 1,2,3,4,1,2,3,1,1,2...

我可以通过以下语法实现这一点: df$count <- sequence(rle(df$outcome)$lengths) - 0

但是,想象一下,我在 100 次抛硬币中进行了几轮。回合的长度不等,我需要在计数列中将它们分开:

Toss   Round  Outcome  Count
1      1      H        1
2      1      H        2
3      1      H        3
4      1      H        4
5      1      T        1
6      2      T        1
7      2      T        2
8      2      H        1
...

如何在我的代码中的轮次之间实现这种区分(即在结果中计数时按轮次分组)?

编辑:只是想说明这是我需要在 46.000 行数据集中执行的操作的一个非常简化的版本,因此该解决方案不能基于我提供的表,但最好使用 rle-code 或同等代码。

谢谢!

【问题讨论】:

    标签: r run-length-encoding


    【解决方案1】:

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

    D <- read.table(header=TRUE, text=
    "Toss   Round  Outcome  Count
    1      1      H        1
    2      1      H        2
    3      1      H        3
    4      1      H        4
    5      1      T        1
    6      2      T        1
    7      2      T        2
    8      2      H        1")
    
    D$C <- ave(D$Toss, D$Round, D$Outcome, FUN=seq_along)
    D
    #   Toss Round Outcome Count C
    # 1    1     1       H     1 1
    # 2    2     1       H     2 2
    # 3    3     1       H     3 3
    # 4    4     1       H     4 4
    # 5    5     1       T     1 1
    # 6    6     2       T     1 1
    # 7    7     2       T     2 2
    # 8    8     2       H     1 1
    

    data.table:

    library("data.table")
    
    D <- fread(
    "Toss   Round  Outcome  Count
    1      1      H        1
    2      1      H        2
    3      1      H        3
    4      1      H        4
    5      1      T        1
    6      2      T        1
    7      2      T        2
    8      2      H        1")
    
    D[, C:=1:.N, .(Round, Outcome)][]
    

    【讨论】:

    • 谢谢,但由于某种原因,它在我的真实数据集上无法正常工作。它不会停止计数,因此不是在一系列相反的结果之后从 1 重新开始计数,而是从中断的地方继续。所以我得到 1,2,3,4,1,2,3,5,... 我真的不明白为什么,因为它看起来很简单。
    • @Astcar 请提供与您的真实数据等效的示例数据,以便我可以更改我的代码。请阅读stackoverflow.com/questions/5963269/… ...然后编辑您的问题。
    【解决方案2】:

    这是data.table 解决方案:

    library(data.table)
    
    DF <- data.frame(
      stringsAsFactors = FALSE,
                  Toss = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L),
                 Round = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L),
               Outcome = c("H", "H", "H", "H", "T", "T", "T", "H")
    )
    
    setDT(DF)
    
    DF[, .(Toss, Count = seq_len(.N)), by = .(Round, Outcome)]
    

       Round Outcome Toss Count
    1:     1       H    1     1
    2:     1       H    2     2
    3:     1       H    3     3
    4:     1       H    4     4
    5:     1       T    5     1
    6:     2       T    6     1
    7:     2       T    7     2
    8:     2       H    8     1
    

    【讨论】:

      【解决方案3】:

      另一个应该更快的data.table 选项:

      DT[, Count := rowid(rleid(Round, Outcome))]
      

      输出:

         Toss Round Outcome Count
      1:    1     1       H     1
      2:    2     1       H     2
      3:    3     1       H     3
      4:    4     1       H     4
      5:    5     1       T     1
      6:    6     2       T     1
      7:    7     2       T     2
      8:    8     2       H     1
      

      数据:

      library(data.table)
      DT <- fread("Toss   Round  Outcome  Count
      1      1      H        1
      2      1      H        2
      3      1      H        3
      4      1      H        4
      5      1      T        1
      6      2      T        1
      7      2      T        2
      8      2      H        1")
      

      【讨论】:

      • 哦,也许你也可以帮我解决一个后续问题?我需要一个列,它仅基于 n+1 为每个计数组提供一个标识,以便每次 Count==1 启动一个新的计数组(即在示例中,第 1-4 行将是计数组 1 ,第 5 行=计数组 2,第 6+7 行=计数组 3,等等。我很感激!
      • 也许是DT[, Count := rowid(rleid(Round, Outcome))][, CountGroup := cumsum(Count==1L)]
      • 确实如此!非常感谢!
      【解决方案4】:
      library(dplyr)
      
      df = read.table(text = "
      Toss   Round  Outcome  Count
      1      1      H        1
      2      1      H        2
      3      1      H        3
      4      1      H        4
      5      1      T        1
      6      2      T        1
      7      2      T        2
      8      2      H        1
      ", header=T)
      
      df %>%
        group_by(Round, Outcome) %>%
        mutate(NewCount = row_number()) %>%
        ungroup()
      
      # # A tibble: 8 x 5
      #    Toss Round Outcome Count NewCount
      #   <int> <int> <fct>   <int>    <int>
      # 1     1     1 H           1        1
      # 2     2     1 H           2        2
      # 3     3     1 H           3        3
      # 4     4     1 H           4        4
      # 5     5     1 T           1        1
      # 6     6     2 T           1        1
      # 7     7     2 T           2        2
      # 8     8     2 H           1        1
      

      【讨论】:

      • 当我尝试使用 dplyr 时出现此错误:Error: .onLoad failed in loadNamespace() for 'vctrs', details: call: loadNamespace(name) error: there is no package called ‘backports’
      • 不知道为什么,但请确保您的软件包都是最新的。看起来像一个依赖问题/冲突。
      猜你喜欢
      • 1970-01-01
      • 2021-11-15
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      • 2017-11-29
      • 1970-01-01
      相关资源
      最近更新 更多