These are some functions we can use when we need to compare two different sets in regard to the elements they contain. Here we will be comparing data frames where the elements of the sets are defined as their rows.

(set1 <- df %>% 
  slice(1:10))
A tibble: 10 x 8
(set2 <- df %>% 
  slice(6:15))
A tibble: 10 x 8

- intersect()

intersect() returns the unique elements common to both sets, like an AND.

intersect(set1,
          set2)
A tibble: 5 x 8

- union()

union() merges the two sets, keeping only the unique elements, like an OR.

union(set1,
      set2)
A tibble: 15 x 8

- union_all()

If we want to keep the duplicates as well we must use union_all().

union_all(set1,
          set2)
A tibble: 20 x 8

- setdiff()

setdiff() returns the unique elements of the set specified first not present in the one specified second.

setdiff(set1,
        set2)
A tibble: 5 x 8
setdiff(set2,
        set1)
A tibble: 5 x 8

- symdiff()

symdiff() returns the unique elements of the set specified first not present in the one specified second, together with the unique elements of the set specified second not present in the one specified first, thus not returning the elements present in both sets, like the filter() helper xor().

symdiff(set1,
        set2)
A tibble: 10 x 8

- setequal() / identical()

setequal() returns logical values, TRUE if the two sets are equal and FALSE otherwise.

setequal(set1,
         set1)
## [1] TRUE
setequal(set1,
         set2)
## [1] FALSE

For this task though identical() from base R is more strict and to be preferred in my opinion.

setequal(set1,
         set1 %>%
           arrange(desc(Invoice)))
## [1] TRUE
identical(set1,
          set1 %>%
           arrange(desc(Invoice)))
## [1] FALSE
identical(df,
          df %>% 
            select(8:1))
## [1] FALSE
identical(df,
          df %>%
            group_by(Country))
## [1] FALSE

- is.element()

We can use is.element() if we want to know if one value is contained in a particular set.

is.element("WHITE CHERRY LIGHTS", unlist(set1))
## [1] TRUE

The set must be a vector, that’s why we used unlist() (in R, a data frame is a list of vectors).

- consistency of sets

For all these functions is important that the sets we compare are of the same class, otherwise we will get an error if the first object is a data frame and the second one a vector.

intersect(df %>% 
            select(Invoice),
          df$Invoice)
Error in `intersect()`:
! `x` and `y` are not compatible.
`y` must be a data frame.
union(df %>% 
        select(Invoice),
      df$Invoice)
Error in `union()`:
! `x` and `y` are not compatible.
`y` must be a data frame.
union_all(df %>%
            select(Invoice),
          df$Invoice)
Error in `union_all()`:
! `x` and `y` are not compatible.
`y` must be a data frame.
setdiff(df %>% 
          select(Invoice),
        df$Invoice)
Error in `setdiff()`:
! `x` and `y` are not compatible.
`y` must be a data frame.
symdiff(df %>% 
          select(Invoice),
        df$Invoice)
Error in `symdiff()`:
! `x` and `y` are not compatible.
`y` must be a data frame.
setequal(df %>%
           select(Invoice),
         df$Invoice)
Error in `setequal()`:
! `y` must be a data frame.

And incongruous results, bar for setequal() and an error for union_all(), if the first object is a vector.

intersect(df$Invoice[1:10],
          set2 %>% 
            select(Invoice))
## list()
union(df$Invoice[1:10],
      set2 %>% 
        select(Invoice))
## [[1]]
## [1] "489434"
## 
## [[2]]
## [1] "489435"
## 
## [[3]]
##  [1] "489434" "489434" "489434" "489435" "489435" "489435" "489435" "489436"
##  [9] "489436" "489436"
union_all(df$Invoice[1:10],
          set2 %>% 
            select(Invoice))
## Error in `vec_c()`:
## ! Can't combine `..1` <character> and `..2` <tbl_df>.
setdiff(df$Invoice[1:10],
        set2 %>% 
          select(Invoice))
## [1] "489434" "489435"
symdiff(df$Invoice[1:10],
        set2 %>% 
          select(Invoice))
## [[1]]
## [1] "489434"
## 
## [[2]]
## [1] "489435"
## 
## [[3]]
##  [1] "489434" "489434" "489434" "489435" "489435" "489435" "489435" "489436"
##  [9] "489436" "489436"
setequal(df$Invoice[1:10],
         set2 %>% 
          select(Invoice))
## [1] FALSE

When the two objects are both data frames is important that the columns are the same (in names and types as well).

intersect(set1 %>%
            select(1:7),
          set2)
Error in `intersect()`:
! `x` and `y` are not compatible.
✖ Different number of columns: 7 vs 8.
union(set1 %>%
        select(1:7),
      set2)
Error in `union()`:
! `x` and `y` are not compatible.
✖ Different number of columns: 7 vs 8.
union_all(set1 %>%
            select(1:7),
          set2)
Error in `union_all()`:
! `x` and `y` are not compatible.
✖ Different number of columns: 7 vs 8.
setdiff(set1 %>%
          select(1:7),
        set2)
Error in `setdiff()`:
! `x` and `y` are not compatible.
✖ Different number of columns: 7 vs 8.
symdiff(set1 %>%
          select(1:7),
        set2)
Error in `symdiff()`:
! `x` and `y` are not compatible.
✖ Different number of columns: 7 vs 8.

With two vectors there are no problems.

intersect(set1$Invoice,
          set2$Invoice)
## [1] "489434" "489435"
union(set1$Invoice,
      set2$Invoice)
## [1] "489434" "489435" "489436"
union_all(set1$Invoice,
          set2$Invoice)
##  [1] "489434" "489434" "489434" "489434" "489434" "489434" "489434" "489434"
##  [9] "489435" "489435" "489434" "489434" "489434" "489435" "489435" "489435"
## [17] "489435" "489436" "489436" "489436"
setdiff(set1$Invoice,
        set2$Invoice)
## character(0)
setequal(set1$Invoice,
         set2$Invoice)
## [1] FALSE
symdiff(set1$Invoice,
        set2$Invoice)
## [1] "489436"

- with group_by()

When the data frames are grouped, the output inherits the grouping of the first set.

intersect(set1 %>%
            group_by(Country),
          set2 %>%
            group_by(`Customer ID`))
A tibble: 5 x 8
Groups: Country [1]
union(set1 %>%
        group_by(Country),
      set2 %>%
        group_by(`Customer ID`))
A tibble: 15 x 8
Groups: Country [1]
union_all(set1 %>%
            group_by(Country),
          set2 %>%
            group_by(`Customer ID`))
A tibble: 20 x 8
Groups: Country [1]
setdiff(set1 %>%
          group_by(Country),
        set2 %>%
          group_by(`Customer ID`))
A tibble: 5 x 8
Groups: Country [1]
symdiff(set1 %>%
          group_by(Country),
        set2 %>%
          group_by(`Customer ID`))
A tibble: 10 x 8
Groups: Country [1]