【问题标题】:Counting the result of a left join using dplyr使用 dplyr 计算左连接的结果
【发布时间】:2015-11-05 02:27:03
【问题描述】:

使用 dplyr 计算左外连接结果的正确方法是什么?

考虑两个数据框:

a <- data.frame( id=c( 1, 2, 3, 4 ) )
b <- data.frame( id=c( 1, 1, 3, 3, 3, 4 ), ref_id=c( 'a', 'b', 'c', 'd', 'e', 'f' ) )

a 指定四个不同的 ID。 b 指定了六个引用a 中的 ID 的记录。如果我想查看每个 ID 被引用了多少次,我可以试试这个:

a %>% left_join( b, by='id' ) %>% group_by( id ) %>% summarise( refs=n() )
Source: local data frame [4 x 2]

     id  refs
  (dbl) (int)
1     1     2
2     2     1
3     3     3
4     4     1

但是,结果具有误导性,因为它表明 ID 2 被引用过一次,而实际上它从未被引用过(在中间数据帧中,对于 ID 2,ref_id 是 NA)。我想避免引入单独的库,例如sqldf

【问题讨论】:

  • 不知道为什么有人要否决这个问答...

标签: r dplyr


【解决方案1】:

有了data.table,你可以做到

library(data.table)
setDT(a); setDT(b)

b[a, .N, on="id", by=.EACHI]


   id N
1:  1 2
2:  2 0
3:  3 3
4:  4 1

这里的语法是x[i, j, on, by=.EACHI]

  • .EACHI 指的是i=a 的每一行。
  • j=.N 使用一个特殊的变量来表示行数。

【讨论】:

  • 真的很疯狂而且非常整洁的图书馆。
【解决方案2】:

已经有一些很好的答案,但是由于问题要求不要在这里使用包,因此是其中之一。我们对ab 执行左连接,并附加一个refs 列,如果ref_id 不是NA,则该列为TRUE。然后使用aggregaterefs 列求和:

m <- transform(merge(a, b, all.x = TRUE), refs = !is.na(ref_id))
aggregate(refs ~ id, m, sum)

给予:

  id refs
1  1    2
2  2    0
3  3    3
4  4    1

【讨论】:

    【解决方案3】:

    我很难确定这是一个 hack 还是计算引用的正确方法,但这会返回预期的结果:

    a %>% left_join( b, by='id' ) %>% group_by( id ) %>% summarise( refs=sum( !is.na( ref_id ) ) )
    Source: local data frame [4 x 2]
    
         id  refs
      (dbl) (int)
    1     1     2
    2     2     0
    3     3     3
    4     4     1
    

    【讨论】:

    • tally 是最后一步的另一个选项:a %&gt;% left_join( b, by='id' ) %&gt;% group_by( id ) %&gt;% tally( !is.na( ref_id ) )
    • 谢谢@Frank!我认为tallysummarise 更具可读性,并且它保持在dplyr 之内。
    • 请注意,tally 没有给出所需的列名 refs,而 summarize(refs=...) 给出了。
    【解决方案4】:

    它确实需要另一个包,但我会因为没有提及tidylog 而感到失职,它提供了广泛的 tidyverse 动词的报告。在您的情况下,它会生成如下报告:

    library(tidylog)
    
    a <- data.frame(id = c(1, 2, 3, 4 ))
    b <- data.frame(id = c(1, 1, 3, 3, 3, 4), ref_id = c('a', 'b', 'c', 'd', 'e', 'f'))
    
    a %>% left_join(b, by='id')
    
    left_join: added one column (ref_id)
               > rows only in x   1
               > rows only in y  (0)
               > matched rows     6    (includes duplicates)
               >                 ===
               > rows total       7
    
      id ref_id
    1  1      a
    2  1      b
    3  2   <NA>
    4  3      c
    5  3      d
    6  3      e
    7  4      f
    

    有关更多示例/信息,请参阅 herehere

    【讨论】:

      猜你喜欢
      • 2019-07-29
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 2022-06-17
      • 1970-01-01
      • 2022-11-10
      • 2017-12-08
      • 1970-01-01
      相关资源
      最近更新 更多