632

How to check if a vector contains a given value?

zx8754
  • 52,746
  • 12
  • 114
  • 209
medriscoll
  • 26,995
  • 17
  • 40
  • 36
  • 47
    sometimes I ask myself why R just doesn't use the word contains to make it users easier – greg121 Mar 04 '13 at 17:28
  • 22
    consider that "in" is contained in "conta(in)s"; I'd contend that "in" is a considerably concise contender in this context – hedgedandlevered Mar 11 '16 at 16:34
  • 1
    Perhaps with the addition of flanking `%`-signs that is. The word `in` is a reserved word in R use in for-loop construction. – IRTFM Jul 09 '16 at 00:44
  • @greg121 dplyr already has a [contains](http://dplyr.tidyverse.org/reference/select_helpers.html) function, but it's used for a different purpose: to select a column in a data frame. For example `select(iris, contains("etal"))`. – Paul Rougieux Mar 14 '18 at 09:59
  • Is there a concise way to do it for real valued numbers with a given precision? – mlt Nov 16 '18 at 19:45
  • @mlt - sure, but that's probably a new question. – Ken Williams Jan 14 '19 at 04:54
  • @greg121 `in` also exist in popular languages such as JavaScript, Python and SQL, so not sure what so special about in R in particular- I would even bet R creators took it from one of them. – David Arenburg Aug 07 '19 at 17:14

8 Answers8

600

Both the match() (returns the first appearance) and %in% (returns a Boolean) functions are designed for this.

v <- c('a','b','c','e')

'b' %in% v
## returns TRUE

match('b',v)
## returns the first location of 'b', in this case: 2
Community
  • 1
  • 1
medriscoll
  • 26,995
  • 17
  • 40
  • 36
203

is.element() makes for more readable code, and is identical to %in%

v <- c('a','b','c','e')

is.element('b', v)
'b' %in% v
## both return TRUE

is.element('f', v)
'f' %in% v
## both return FALSE

subv <- c('a', 'f')
subv %in% v
## returns a vector TRUE FALSE
is.element(subv, v)
## returns a vector TRUE FALSE
Justin Nafe
  • 3,002
  • 2
  • 18
  • 16
  • 8
    I know the documentation says `is.element(x, y) is identical to x %in% y`. But, I dont know why, `is.elements` works when mixing integers and numerics and `%in%` doesn't – pomber Dec 28 '14 at 06:21
  • @pomber : Could you give an example of this? – discipulus Jun 27 '17 at 06:24
  • @pomber is it fixed? – vasili111 Sep 21 '19 at 23:28
  • 9
    The superior readability `is.element()` vs `%in%` is subjective. A case can be made that an infix operator is more readable because it eliminates ambiguity in the order of arguments. `apple in fruit` makes sense, `fruit in apple` does not. `is.element(apple, fruit)` or `is.element(fruit, apple)` could both be right depending on implementation of the `is.element` function. – rileymcdowell Jan 03 '20 at 16:36
120

I will group the options based on output. Assume the following vector for all the examples.

v <- c('z', 'a','b','a','e')

For checking presence:

%in%

> 'a' %in% v
[1] TRUE

any()

> any('a'==v)
[1] TRUE

is.element()

> is.element('a', v)
[1] TRUE

For finding first occurance:

match()

> match('a', v)
[1] 2

For finding all occurances as vector of indices:

which()

> which('a' == v)
[1] 2 4

For finding all occurances as logical vector:

==

> 'a' == v
[1] FALSE  TRUE FALSE  TRUE FALSE

Edit: Removing grep() and grepl() from the list for reason mentioned in comments

ishandutta2007
  • 16,676
  • 16
  • 93
  • 129
  • 8
    As already commented [here](https://stackoverflow.com/questions/1169248/r-function-for-testing-if-a-vector-contains-a-given-element/34056066#comment66181358_34056066) and [here](https://stackoverflow.com/questions/1169248/r-function-for-testing-if-a-vector-contains-a-given-element/34056066#comment73025314_34056066), don't use `grep()` or regular expressions to find exact matches. – Uwe Jun 13 '17 at 10:04
71

The any() function makes for readable code

> w <- c(1,2,3)
> any(w==1)
[1] TRUE

> v <- c('a','b','c')
> any(v=='b')
[1] TRUE

> any(v=='f')
[1] FALSE
Dan Goldstein
  • 24,229
  • 18
  • 37
  • 41
  • 11
    Be aware this behaves differently from `%in%`: `any(1==NA)` returns `NA`, where `1 %in% NA` returns `FALSE`. –  Mar 23 '17 at 01:34
  • @user3603486: `any(1==NA, na.rm=TRUE)` returns `FALSE`. – AkselA Apr 23 '19 at 20:57
37

You can use the %in% operator:

vec <- c(1, 2, 3, 4, 5)
1 %in% vec # true
10 %in% vec # false
ars
  • 120,335
  • 23
  • 147
  • 134
20

Also to find the position of the element "which" can be used as

pop <- c(3, 4, 5, 7, 13)

which(pop==13)

and to find the elements which are not contained in the target vector, one may do this:

pop <- c(1, 2, 4, 6, 10)

Tset <- c(2, 10, 7)   # Target set

pop[which(!(pop%in%Tset))]
ah bon
  • 9,293
  • 12
  • 65
  • 148
Armin
  • 301
  • 2
  • 4
  • `which` is actually preferable sometimes for it gives you *all* the matching positions (as an array), unlike `match`. Although this was perhaps not what the OP asked for, unlike http://stackoverflow.com/questions/1169388/finding-multiple-elements-in-a-vector – Fizz Feb 07 '15 at 16:27
  • 2
    Why bother with `which` if you just want to find the elements not in `Tset`? You can just index `pop` directly; `pop[!pop%in%Tset]` – Houshalter Feb 20 '17 at 23:11
12

I really like grep() and grepl() for this purpose.

grep() returns a vector of integers, which indicate where matches are.

yo <- c("a", "a", "b", "b", "c", "c")

grep("b", yo)
[1] 3 4

grepl() returns a logical vector, with "TRUE" at the location of matches.

yo <- c("a", "a", "b", "b", "c", "c")

grepl("b", yo)
[1] FALSE FALSE  TRUE  TRUE FALSE FALSE

These functions are case-sensitive.

ojdajuiceman
  • 361
  • 2
  • 9
  • 12
    By default, `grep` takes a regular expression as its first element, so to do an exact match for `"b"`, either use`^e$` or add `, fixed=TRUE`). – reinierpost Jan 07 '16 at 07:45
  • 12
    Do not use regex for exact matches. This is dangerous and can have unexpected results – David Arenburg Sep 10 '16 at 17:54
  • 10
    Yeah, this is a terrible, no good, very bad idea - inefficient and guaranteed to break. E.g. `myvar <- 'blah'; grepl('b', myvar, fixed=TRUE)` will return `TRUE` even though 'b' is not in `myvar`. –  Mar 23 '17 at 01:31
1

Another option to check if a element exists in a vector is by using the %in{}% syntax from the inops package like this:

library(inops)
#> 
#> Attaching package: 'inops'
#> The following object is masked from 'package:base':
#> 
#>     <<-
v <- c('a','b','c','e')
v %in{}% c("b")
#> [1] FALSE  TRUE FALSE FALSE

Created on 2022-07-16 by the reprex package (v2.0.1)

Quinten
  • 35,235
  • 5
  • 20
  • 53