How to Find the Difference Between Two Vectors in R
R's base setdiff() covers most vector-difference needs in one call, but like every set-based approach it drops duplicates and direction matters. Here are the four approaches worth knowing, including the dplyr equivalent for data frames.
Quick answer
setdiff(a, b) returns elements in a not in b, but treats both as sets - duplicates are dropped and direction matters (setdiff(a, b) differs from setdiff(b, a)). To keep duplicates and original order, use a[!a %in% b] instead. For symmetric difference, use union(setdiff(a, b), setdiff(b, a)). For data frames matched by a key column, use dplyr's anti_join(df_a, df_b, by = 'id').
Need the same thing in another language?
See the full reference for Python, JavaScript, SQL, Java, and more.
setdiff(): the standard base R function
a <- c("apple", "banana", "cherry", "banana")
b <- c("banana", "date")
a_only <- setdiff(a, b)
print(a_only) # "apple" "cherry" - duplicate "banana" dropped, order not guaranteed setdiff(a, b) treats both vectors as sets: any duplicate values in a collapse to one occurrence in the output, and the direction matters - setdiff(b, a) would give you a completely different result (just "date" here).
a[!a %in% b]: preserving duplicates and order
a <- c("apple", "banana", "cherry", "banana")
b <- c("banana", "date")
a_only <- a[!a %in% b]
print(a_only) # "apple" "cherry" - both "banana"s filtered, "apple" and "cherry" keep their position %in% checks each element of a against the whole of b and returns a logical vector, which ! then negates to keep only non-matches. Unlike setdiff(), this is a filter rather than a set operation - it preserves a's original order and any duplicate values that aren't themselves in b.
Symmetric difference: items unique to either vector
a <- c("apple", "banana", "cherry")
b <- c("banana", "date")
sym_diff <- union(setdiff(a, b), setdiff(b, a))
print(sym_diff) # "apple" "cherry" "date" R has no single function for symmetric difference, but combining both one-way setdiff() calls with union() gets there in one line - everything unique to a plus everything unique to b.
dplyr anti_join(): the data frame equivalent
library(dplyr)
df_a <- data.frame(id = c(1, 2, 3), name = c("a", "b", "c"))
df_b <- data.frame(id = c(2, 3, 4), name = c("b", "c", "d"))
only_in_a <- anti_join(df_a, df_b, by = "id")
print(only_in_a) # row with id = 1 When you're comparing data frames rather than plain vectors and want to match rows by a key column, anti_join() is the tidyverse equivalent of a vector difference - it returns rows from df_a whose id doesn't appear in df_b, without requiring the two frames to have identical columns the way setdiff() on whole data frames would.
NA handling: the pitfall that catches people out
NA in R is never equal to another NA under standard equality rules, but %in% and setdiff() specifically treat NA as matching NA - which is the opposite of what == would do. If your vectors contain NA values and you need standard IEEE-style behavior instead, filter them out explicitly with na.omit() before comparing.
Just need the answer, not the code? Paste both lists.
Open Compare 2 Lists →Frequently Asked Questions
What is setdiff() in R and does direction matter?
setdiff(a, b) returns elements in a that are not in b. Direction matters and is not commutative: setdiff(a, b) and setdiff(b, a) give different results unless the two vectors happen to be identical.Does setdiff() preserve duplicates?
setdiff() treats both vectors as sets, so duplicate values within a collapse to a single occurrence in the result - even if that value doesn't appear in b at all. If you need duplicates preserved, use a[!a %in% b] instead.What is the difference between setdiff(a, b) and a[!a %in% b]?
setdiff(a, b) deduplicates the result and doesn't guarantee the original order. a[!a %in% b] keeps every element of a not found in b, including duplicates, in a's original order - it's a filter, not a set operation.How do I get the symmetric difference between two vectors in R?
union(setdiff(a, b), setdiff(b, a)) combines everything unique to a with everything unique to b.Why do factors behave differently from character vectors in setdiff()?
as.character() before comparing to avoid this entirely.