【问题标题】:In dplyr, what are the intrinsic differences between setdiff and anti_join?在 dplyr 中,setdiff 和 anti_join 的本质区别是什么?
【发布时间】:2017-10-20 17:10:47
【问题描述】:

我仍在学习 DataCamp for R 的课程,所以如果这个问题看起来很幼稚,请原谅我。

考虑以下(非常人为的)示例:

library(dplyr)
library(tibble)

type <- c("Dog", "Cat", "Cat", "Cat")
name <- c("Ella", "Arrow", "Gabby", "Eddie")
pets = tibble(name, type)

name <- c("Ella", "Arrow", "Dog")
type <- c("Dog", "Cat", "Calvin")
favorites = tibble(name, type)

anti_join(favorites, pets, by = "name")
setdiff(favorites, pets, by = "name")

这两者都返回完全相同相同的数据:

> anti_join(favorites, pets, by = "name")
# A tibble: 1 × 2
   name   type
  <chr>  <chr>
1   Dog Calvin

> setdiff(favorites, pets, by = "name")
# A tibble: 1 × 2
   name   type
  <chr>  <chr>
1   Dog Calvin

他们每个人的文档似乎只表明了一个细微的区别:setdiff 返回行,但 anti_join 没有。根据我的测试,情况似乎并非如此。

有人可以向我解释这两者之间的真正区别,也许可以提供一个更好的例子来更清楚地说明这些区别吗? (这是 DataCamp 没有特别有用的领域。)

【问题讨论】:

  • dplyr::setdiff 兑现 by 参数/键?
  • @lukeA 我在执行后直接从 RStudio 中复制了该代码。因此,如果对setdiff 的调用已从dplyr 包中解决,我会假设是这样。根据dplyr 文档,setdiff 的签名是setdiff(x, y, ...),因此它接受传递给其他调用的参数。也许我只是走运了。 :)

标签: r dplyr


【解决方案1】:

都是第一个参数的子集,但setdiff 要求列相同:

library(dplyr)

setdiff(mtcars, mtcars[1:30, ])
#>    mpg cyl disp  hp drat   wt qsec vs am gear carb
#> 1 15.0   8  301 335 3.54 3.57 14.6  0  1    5    8
#> 2 21.4   4  121 109 4.11 2.78 18.6  1  1    4    2

setdiff(mtcars, mtcars[1:30, 1:6])
#> Error in setdiff_data_frame(x, y): not compatible: Cols in x but not y: `carb`, `gear`, `am`, `vs`, `qsec`.

anti_join 是一个连接,所以不是:

anti_join(mtcars, mtcars[1:30, 1:3])
#> Joining, by = c("mpg", "cyl", "disp")
#>    mpg cyl disp  hp drat   wt qsec vs am gear carb
#> 1 15.0   8  301 335 3.54 3.57 14.6  0  1    5    8
#> 2 21.4   4  121 109 4.11 2.78 18.6  1  1    4    2

【讨论】:

  • 那么区别在于他们如何比较数据? setdiff 通过比较整行来做到这一点,而 anti_join 只比较键?
  • 对。 dplyr::setdiffbase::setdiff(1:10, 1:8) 的工作方式类似,但将行作为值,这意味着每个行都必须相同才能被丢弃。 anti_join 只是尝试匹配指定/匹配的列。
【解决方案2】:

setdiff 和anti_join 之间的一个区别是您可以选择anti_join 中的列。例如:

df1 <- data.frame(a = c(1,3,5,4), b = c(5,6,7,8))
df2 <- data.frame( a = c(1,2,3,4), b = c(5,9,7,8))
#df1 looks like        df2 look like
# a   b                a   b    
# 1   5                1   5
# 3   6                2   9 
# 5   7                3   7
# 4   8                4   8

set_diff(x,y)

#The first and last rows of df1 and df2 are identical. 
#So set_diff(df1,df2) will return the 2nd and 3rd row of df1

#a b
#3 6
#5 7

#If I do the same thing with anti_join, I get the same results
anti_join(df1,df2)

#a b
#3 6
#5 7
#However,...if I only care about values in df1 column 'b' that are different from the 
# corresponding value in column b of df2... I can use the option "by" parameter..

anti_join(df1,df2, by = 'b')

 #Since column the only number in column b of df1 that is different 
#from the corresponding value in df2 is row two, 
#this returns row 2 of df1

#a b
#3 6

另一个区别是,在 set_diff 中,两个数据帧必须具有相同的列。

#Keeping df1 identical to df1 in the previous example... 
# and df2 the same but with an additional column

df1 <- data.frame(a = c(1,3,5,4), b = c(5,6,7,8))
df2 <- data.frame(a = c(1,2,3,4), b = c(5,9,7,8), l = c(9,9,9,9))

#df1 looks like        df2 look like
# a   b                a   b  c   
# 1   5                1   5  9
# 3   6                2   9  9 
# 5   7                3   7  9
# 4   8                4   8  9

setdiff(df1,df2)
#Returns:
# Error in setdiff_data_frame(x, y) : 
# not compatible: Cols in y but not x: `l`. 

anti_join(df1,df2)
#Ignores column 3 of df2, since there is no corresponding column in df1.  
#Returns: rows in df1 in which (a,b) are not equal to (a,b) in df2 
#(which will be identical to the output when df2 didn't have 
#a third column).

# a b
# 3 6
# 5 7

anti_join(df1,df2, by = 'b')

#Since column the only number in column b of df1 that is different
# from the corresponding value in df2 is row two, this returns row 2 of   df1...
#...same as when df2 only had two columns

【讨论】:

    猜你喜欢
    • 2017-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    相关资源
    最近更新 更多