dplyr::left_join 是不是等同于 base::merge(..., all.x=TRUE)?

Posted

技术标签:

【中文标题】dplyr::left_join 是不是等同于 base::merge(..., all.x=TRUE)?【英文标题】:Is dplyr::left_join equivalent to base::merge(..., all.x=TRUE)?dplyr::left_join 是否等同于 base::merge(..., all.x=TRUE)? 【发布时间】:2018-08-06 01:30:03 【问题描述】:

我有很多旧的 R 代码使用以下语法来执行我认为的左连接(或者如果您更喜欢 SQL 名称,则为左外连接):

merge(a, b, by="id", all.x=TRUE)

在我看来,这完全等同于使用dplyr的专用功能:

left_join(a, b, by="id")

我想知道这是否总是如此,或者两者在某些情况下是否会导致不同的结果。请随时提供示例,说明何时可以将它们视为等效,何时不等效。

在这个愚蠢的例子中,两者似乎产生了相同的结果

require(dplyr)

a = data.frame(id=1:4, c(letters[1:3], NA)) %>% as_tibble()
b = data.frame(id=1:2) %>% as_tibble()

all_equal(left_join(b, a, by="id"), merge(b, a, by='id', all.x = T))
# TRUE

我为什么要问这个问题?

我问这个是因为,例如,stats::aggregate 和 dplyr::group_by,如果与默认参数一起使用,则等效:

a %>% group_by(letter) %>% summarise(mean(id))

# # A tibble: 4 x 2
# letter `mean(id)`
# <fct>       <dbl>
# 1 a            1.00
# 2 b            2.00
# 3 c            3.00
# 4 <NA>         4.00

aggregate(id ~ letter, data = a, FUN = mean)

# letter id
# 1      a  1
# 2      b  2
# 3      c  3 

如果您从 dplyr 的数据中省略 NA,它们是否会给出相同的结果(因为聚合的默认值是 na.omit)。我也在问,因为在处理大型数据集时,很难一眼看出为什么会发生某些事情(尤其是在处理一些不是你编写的代码时),如果你必须做一些维护工作,像那些无害的组织上面介绍的可能会导致输出发生重大变化。

编辑:我正在使用 dplyr 0.7.4 和 R 3.4.1。

【问题讨论】:

请注意,merge 可能会重新排序数据。请参阅?merge:“默认情况下,行在公共列上按字典顺序排序,但sort = FALSE 的顺序为未指定的顺序。”参见例如Merge two data frames while keeping the original row order 有趣。当使用带有默认参数的 all_equal 检查相等性时,这当然不会出现。 【参考方案1】:

tidyverse 函数使用 de NA 作为数据的一部分,因为它应该解释“已识别”数据无法解释的信息的某些方面。换句话说,您必须使用特定的函数来删除NA values。在您的示例中,有许多方法可以执行相同的过程并获得相同的结果。例如,考虑na.omit() 函数:

library(tidyverse) #This include dplyr package

a = data.frame(id = 1:4, 
               letter = c(letters[1:3], NA)
               ) %>% as_tibble()

all.equal(
  a %>% 
    na.omit(letter) %>% #This drop NA values in the column "letter" 
    group_by(letter) %>% 
    summarise(id = mean(id)),

  aggregate(id ~ letter, 
            data = a, 
            FUN = mean ))
#>[1] TRUE

其他例子是使用filter()函数:

all.equal(
  a %>% 
    filter(!is.na(letter)) %>% #This drop NA values in the column "letter" 
    group_by(letter) %>% 
    summarise(id = mean(id)),

  aggregate(id ~ letter, 
            data = a, 
            FUN = mean ))
#>[1] TRUE

希望能帮到你!

【讨论】:

以上是关于dplyr::left_join 是不是等同于 base::merge(..., all.x=TRUE)?的主要内容,如果未能解决你的问题,请参考以下文章

使用 by=c(x=y) 错误在函数内执行 dplyr::left_join

dplyr left_join 小于,大于条件

使用datetime列的r dplyr :: left_join无法正确连接

dplyr :: left_join()产生意外错误

DataLog 是不是等同于 SQL?

Java 包是不是等同于 .Net 程序集?