【问题标题】:Group counter that restarts (with R data.table) [duplicate]重新启动的组计数器(使用 R data.table)[重复]
【发布时间】:2018-06-03 20:38:55
【问题描述】:

这与Create sequential counter that restarts on a condition within panel data groupsdata.table "key indices" or "group counter" 有点相关,但并不完全相同。

# data table:
    x y i d
 1: A B 1 1
 2: A B 1 1
 3: A C 2 2
 4: A D 3 3
 5: B A 1 4
 6: B A 1 4 
 7: C A 1 4
 8: C A 1 4 
 9: C B 2 5
10: C C 3 6
11: C C 3 6
12: C D 4 7

使用dt[, d:= .GRP, by = .(x,y)] 可以生成最后一列。然而,我正在寻找一个在每个 x 组内重新启动的计数器。有关所需结果,请参阅列 i

【问题讨论】:

  • 如果您有data.table(x = "A", y = c("A", "B", "A")),您希望d 是什么?
  • 您可以通过您的方法进行算术运算:tab[, g0 := .GRP, by=.(x,y)][, g := g0 - first(g0) + 1L, by=x][]
  • 作为骗子关闭,但如果您不同意,请告诉我。我建议阅读马特的回答,它显示了我上一条评论中提到的方法。

标签: r data.table


【解决方案1】:

您可以通过y 列上的rleid 函数来实现这一点,该列由x 分组。 rleid 是一种计数器,每次发生变化时都会增加,否则保持不变

library(data.table)
tab <- fread("
x y i d
A B 1 1
A B 1 1
A C 2 2
A D 3 3
B A 1 4
B A 1 4 
C A 1 4
C A 1 4 
C B 2 5
C C 3 6
C C 3 6
C D 4 7")

dt <- tab[, .(x, y, i)]
dt[, d:= rleid(y), by = .(x)]
dt
#>     x y i d
#>  1: A B 1 1
#>  2: A B 1 1
#>  3: A C 2 2
#>  4: A D 3 3
#>  5: B A 1 1
#>  6: B A 1 1
#>  7: C A 1 1
#>  8: C A 1 1
#>  9: C B 2 2
#> 10: C C 3 3
#> 11: C C 3 3
#> 12: C D 4 4

reprex package (v0.2.0) 于 2018 年 6 月 3 日创建。

【讨论】:

    【解决方案2】:

    如果您的数据不是由yx 中排序的,您可以这样做

    df[, i := .SD[, rep(.GRP, .N), y]$V1, x]
    

    df[, i := {ord <- order(y); rleid(y[ord])[order(ord)]}, x]
    

    但是,如果顺序不重要,那么在计算 i 之前通过 y 订购会更快

    setorder(df, y) 
    df[, i := rleid(y), x]
    

    比较

    df <- df[sample(nrow(df), 1e7, T)]
    
    grp <- function(df) df[, i := .SD[, rep(.GRP, .N), y]$V1, x]
    rleid.alone <- function(df) 
      df[, i := rleid(y), x]
    setord.rleid <- function(df) {
      setorder(df, y); df[, i := rleid(y), x]}
    ord.rleid <- function(df){ 
        df[, i := {ord <- order(y); rleid(y[ord])[order(ord)]}, x]}
    microbenchmark(
      rleid.alone(df),
      setord.rleid(df),
      ord.rleid(df),
      grp(df),
      times = 10
    )
    
    # Unit: milliseconds
    # expr                   min        lq      mean    median        uq        max neval
    # rleid.alone(df)   196.5973  201.1499  237.3837  234.6709  262.0397   292.0986    10
    # setord.rleid(df)  215.6894  248.7814  285.1045  273.7231  316.5271   382.6173    10
    # ord.rleid(df)    7610.9995 7767.9028 8137.2361 7820.5919 8055.2610 10034.9907    10
    # grp(df)           336.3208  357.3206  439.5327  394.6960  517.3482   719.8893    10
    

    【讨论】:

      【解决方案3】:

      我发现首先考虑算法,然后考虑 data.table(或基本 R 或 dplyr)应用程序很有帮助。似乎有几种可能的算法来创建所需的计数器。我有

      f0 = function(x) match(x, unique(x))
      

      或者如果要对 x 的值进行排序

      f1 = function(x) match(x, sort(unique(x)))
      

      这些不同于基于 x 中运行的索引

      f2 = function(x) { r = rle(x); r$values = seq_along(r$values); inverse.rle(r) }
      

      我们有其他答案

      f3 = function(x) { o <- order(x); rleid(x[o])[order(o)] }
      

      data.table::rleid()

      这里是不同功能的快速比较

      > set.seed(123); x = sample(5, 20, TRUE)
      > f0(x); f1(x); f2(x); f3(x); rleid(x)
       [1] 1 2 3 4 4 5 3 4 3 3 4 3 2 3 5 4 1 5 1 4
       [1] 2 4 3 5 5 1 3 5 3 3 5 3 4 3 1 5 2 1 2 5
       [1]  1  2  3  4  4  5  6  7  8  8  9 10 11 12 13 14 15 16 17 18
       [1] 2 4 3 5 5 1 3 5 3 3 5 3 4 3 1 5 2 1 2 5
       [1]  1  2  3  4  4  5  6  7  8  8  9 10 11 12 13 14 15 16 17 18
      

      澄清实现 f0-f2 各不相同,f2()rleid() 似乎至少对于 f 的域是相同的,f1() 似乎是@Ryan 的解决方案f3()

      有趣的是,问题中提供的数据并没有区分这些实现(我执行 data.table 步骤对吗?)

      > dt = tab[, .(x, y, i)]
      > (dt[, .(y = y, f0 = f0(y), f1 = f1(y), f2 = f2(y), rleid = rleid(y)), by = .(x)])
          x y f0 f1 f2 rleid
       1: A B  1  1  1     1
       2: A B  1  1  1     1
       3: A C  2  2  2     2
       4: A D  3  3  3     3
       5: B A  1  1  1     1
       6: B A  1  1  1     1
       7: C A  1  1  1     1
       8: C A  1  1  1     1
       9: C B  2  2  2     2
      10: C C  3  3  3     3
      11: C C  3  3  3     3
      12: C D  4  4  4     4
      

      建立不同的算法后,可能比较性能以区分替代实现。

      > x = sample(100, 10000, TRUE)
      > microbenchmark(f0(x), f1(x), f2(x), f3(x), rleid(x))
      Unit: microseconds
           expr      min        lq      mean   median        uq      max neval
          f0(x)  818.773  856.5275  926.5475  880.014  906.6040 5273.431   100
          f1(x) 1026.094 1084.1425 1112.1629 1101.626 1133.4100 1384.260   100
          f2(x) 1362.461 1428.8665 1595.0777 1622.881 1672.9835 4253.685   100
          f3(x)  823.653  862.5090  893.1710  894.268  914.1290 1050.157   100
       rleid(x)  236.590  245.0090  252.4963  251.158  257.7365  309.326   100
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-01
        • 2021-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多