【问题标题】:data.table equivalent of tidyr::complete with group_by with on and by syntaxdata.table 等效于 tidyr::complete 与 group_by 与 on 和 by 语法
【发布时间】:2019-07-01 22:18:51
【问题描述】:

问题:

data.table 等效于tidyrcomplete 命令with group by 是什么?

onby对于data.table有什么关系?

示例:

dt=data.table(a = c(1,1,2,2,3,3,4,4) , b = c(4,5,6,7,8,9,10,11) , c = c("x","x","x","x","y","y","y","y"))
show(dt)

   a  b c
1: 1  4 x
2: 1  5 x
3: 2  6 x
4: 2  7 x
5: 3  8 y
6: 3  9 y
7: 4 10 y
8: 4 11 y

目标是获得以下内容:

a  b c
1  4 x
1  5 x
1  6 x
1  7 x
2  4 x
2  5 x
2  6 x
2  7 x
3  8 y
3  9 y
3 10 y
3 11 y
4  8 y
4  9 y
4 10 y
4 11 y

大概是这样的:

setDT(dt)[CJ(a=a,b=b,unique=TRUE), on=.(a,b) , by = .(c)]

但它不起作用,data.table 文档在这方面的语法方面很薄。

解决方案不足:

以下 SO 帖子解决了类似的问题,但在此上下文中未提供足够的解决方案。

【问题讨论】:

    标签: r group-by data.table tidyr


    【解决方案1】:

    试试这个:

    dt[, CJ(a = a, b = b, unique = TRUE), by = "c"]
    

    给予:

        c a  b
     1: x 1  4
     2: x 1  5
     3: x 1  6
     4: x 1  7
     5: x 2  4
     6: x 2  5
     7: x 2  6
     8: x 2  7
     9: y 3  8
    10: y 3  9
    11: y 3 10
    12: y 3 11
    13: y 4  8
    14: y 4  9
    15: y 4 10
    16: y 4 11
    

    【讨论】:

    • 为什么不再需要on
    • on 用于进行合并,但这里没有合并。
    • 在真实数据集中,我丢失了所有额外的列。我的错,。我将更新示例
    • 在这种情况下进行合并。
    【解决方案2】:

    complete 保留了其他不相关的列,所以我会添加一个...

    library(data.table)
    dt = data.table(
      a = c(1,1,2,2,3,3,4,4) , 
      b = c(4,5,6,7,8,9,10,11) , 
      c = c("x","x","x","x","y","y","y","y"),
      d = LETTERS[10 + 1:8])
    
       a  b c d
    1: 1  4 x K
    2: 1  5 x L
    3: 2  6 x M
    4: 2  7 x N
    5: 3  8 y O
    6: 3  9 y P
    7: 4 10 y Q
    8: 4 11 y R
    

    要完成每个 c 的 a x b 组合,我会用这些组合创建一个新表(与@G.Grothendieck 的回答中已经完全一样)并更新连接以获取 d 和其他非组合列:

    mDT = dt[, CJ(a = a, b = b, unique=TRUE), by=c]
    cvars = copy(names(mDT))
    ovars = setdiff(names(dt), cvars)
    
    mDT[, (ovars) := dt[.SD, on=cvars, mget(sprintf("x.%s", ovars))]]
    setcolorder(mDT, names(dt))
    
        a  b c    d
     1: 1  4 x    K
     2: 1  5 x    L
     3: 1  6 x <NA>
     4: 1  7 x <NA>
     5: 2  4 x <NA>
     6: 2  5 x <NA>
     7: 2  6 x    M
     8: 2  7 x    N
     9: 3  8 y    O
    10: 3  9 y    P
    11: 3 10 y <NA>
    12: 3 11 y <NA>
    13: 4  8 y <NA>
    14: 4  9 y <NA>
    15: 4 10 y    Q
    16: 4 11 y    R
    

    或者,您可以进行内部 (?) 联接,但这效率低下,因为它会创建两个新表:

    dt[mDT, on=cvars]
    
    # or more concisely....
    
    dt[dt[, CJ(a = a, b = b, unique=TRUE), by=c], on=.(a,b,c)]
    

    或者,每个by= 组(来自@eddi)进行一次内连接:

    dt[, .SD[CJ(a = a, b = b, unique = TRUE), on = .(a, b)], by = c]
    

    在tidyverse中进行比较:

    library(dplyr); library(tidyr)
    data.frame(dt) %>% group_by(c) %>% complete(a, b)
    
    # A tibble: 16 x 4
    # Groups:   c [2]
       c         a     b d    
       <chr> <dbl> <dbl> <chr>
     1 x         1     4 K    
     2 x         1     5 L    
     3 x         1     6 <NA> 
     4 x         1     7 <NA> 
     5 x         2     4 <NA> 
     6 x         2     5 <NA> 
     7 x         2     6 M    
     8 x         2     7 N    
     9 y         3     8 O    
    10 y         3     9 P    
    11 y         3    10 <NA> 
    12 y         3    11 <NA> 
    13 y         4     8 <NA> 
    14 y         4     9 <NA> 
    15 y         4    10 Q    
    16 y         4    11 R    
    

    【讨论】:

    • 如果c 值不多,我会使用dt[, .SD[CJ(a = a, b = b, unique = TRUE), on = .(a, b)], by = c]
    【解决方案3】:

    下面会返回想要的结果。

    library(data.table)
    dt=data.table(a = c(1,1,2,2,3,3,4,4) , 
                  b = c(4,5,6,7,8,9,10,11) , 
                  c = c("x","x","x","x","y","y","y","y"))
    dttrue <- fread('a  b c
                    1  4 x
                    1  5 x
                    1  6 x
                    1  7 x
                    2  4 x
                    2  5 x
                    2  6 x
                    2  7 x
                    3  8 y
                    3  9 y
                    3 10 y
                    3 11 y
                    4  8 y
                    4  9 y
                    4 10 y
                    4 11 y')
    dt2 <- dt[,CJ(a=a,b=b,unique = TRUE),by = c]
    all.equal(dt2[,.(a,b,c)], dttrue) #true
    

    【讨论】:

      猜你喜欢
      • 2018-04-16
      • 2016-01-03
      • 2017-09-14
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多