代码之家  ›  专栏  ›  技术社区  ›  IceCreamToucan

选择要保留/放入数据的组。桌子

  •  3
  • IceCreamToucan  · 技术社区  · 7 年前

    如何根据数据中的条件删除/保留组。桌子有没有比添加一个新列,然后在该列上过滤并删除它更好的方法?

    set.seed(0)
    dt <- data.table(a = rep(1:3, rep(3, 3)), b = sample(1:5, 9, T))
    
    #    a b
    # 1: 1 4
    # 2: 1 1
    # 3: 1 2
    # 4: 2 1
    # 5: 2 4
    # 6: 2 2
    # 7: 3 4
    # 8: 3 3
    # 9: 3 4
    
    #data.table
    dt[, keep := 2 %in% b, by = a][keep == T][, keep := NULL][]
    #    a b
    # 1: 1 5
    # 2: 1 2
    # 3: 1 2
    # 4: 2 3
    # 5: 2 5
    # 6: 2 2
    
    # dplyr
    dt %>% 
      group_by(a) %>% 
      filter(2 %in% b)
    
    # # A tibble: 6 x 2
    # # Groups:   a [2]
    #       a     b
    #   <int> <int>
    # 1     1     5
    # 2     1     2
    # 3     1     2
    # 4     2     3
    # 5     2     5
    # 6     2     2
    

    基准测试,查看是否 .I 速度更快。2015 Macbook Pro

    bench <- 
      map(10^(4:7)
          , ~ {
            df <- data.table(name = sample(1:.x, 3*.x, T)
                             , a = runif(3*.x)
                             , b = runif(3*.x)
                             , c = runif(3*.x))
    
            dt <- data.table(a = rep(1:.x, rep(10, .x)), b = sample(1:10, 10*.x, T))
    
            microbenchmark(dt[, if(2 %in% b) .SD, a]
                          , dt[dt[, .I[2 %in% b], a]$V1] )
          })
    
    
    bench
    
    [[1]]
    Unit: milliseconds
                             expr      min       lq     mean   median       uq       max neval
       dt[, if (2 %in% b) .SD, a] 13.04827 17.36046 21.15155 19.19119 22.94641  43.04519   100
     dt[dt[, .I[2 %in% b], a]$V1] 17.32547 22.92023 27.09775 24.87586 28.39789 108.47604   100
    
    [[2]]
    Unit: milliseconds
                             expr      min       lq     mean   median       uq      max neval
       dt[, if (2 %in% b) .SD, a] 123.9118 143.7802 162.6719 154.4713 173.2986 428.4141   100
     dt[dt[, .I[2 %in% b], a]$V1] 158.2975 177.3303 206.3611 193.4460 224.5091 435.3982   100
    
    [[3]]
    Unit: seconds
                             expr     min       lq     mean   median       uq      max neval
       dt[, if (2 %in% b) .SD, a] 1.23310 1.351067 1.448680 1.402827 1.517017 1.852797   100
     dt[dt[, .I[2 %in% b], a]$V1] 1.58702 1.704344 1.826468 1.778590 1.947943 2.243176   100
    
    [[4]]
    Unit: seconds
                             expr      min       lq     mean   median       uq      max neval
       dt[, if (2 %in% b) .SD, a] 14.44317 14.65889 14.79806 14.78217 14.91571 15.29134   100
     dt[dt[, .I[2 %in% b], a]$V1] 18.04774 18.36764 18.48804 18.45732 18.53073 20.73805   100
    
    3 回复  |  直到 7 年前
        1
  •  6
  •   IceCreamToucan    7 年前

    您可以使用 if 使用条件 .SD 分组后 dt 按列列出 a :

    dt[, if(2 %in% b) .SD, a]
    
    #   a b
    #1: 1 5
    #2: 1 2
    #3: 1 2
    #4: 2 3
    #5: 2 5
    #6: 2 2
    

    从…起 ?.SD ,则, .SD是一个数据。包含每组x数据子集的表 与…结合 如果 条件,如果 2 不在列中 b 并删除相应的组。

        2
  •  1
  •   FENG QI    7 年前

    我相信这不是最好的解决方案,但这是可行的。

    dt[a%in% dt[, a[2%in%b], by=a][, a],]
    
        3
  •  1
  •   lmo    7 年前

    下面是另一种使用 .I 要返回选定组的行索引,然后返回行上的子集,请执行以下操作:

    dt[dt[, .I[2 %in% b], a]$V1]
       a b
    1: 1 5
    2: 1 2
    3: 1 2
    4: 2 3
    5: 2 5
    6: 2 2