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