How to check if a vector contains a given value?
-
47sometimes I ask myself why R just doesn't use the word contains to make it users easier – greg121 Mar 04 '13 at 17:28
-
22consider 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
-
1Perhaps 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 Answers
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

- 1
- 1

- 26,995
- 17
- 40
- 36
-
-
1Maybe I come a little late. `which(v, 'b')`. Mind the order of the arguments. – Niklas Mertsch Dec 19 '18 at 19:40
-
Your `which(v, 'b')` gives me an error message: >Error in which(v, 'b') : argument to 'which' is not logical – Capt.Krusty Aug 17 '19 at 10:08
-
1The syntax is which(v == b) or any other logical operator. In this case, the return from this would be 2. If v were c("b", "b", "c", "b", "d"), the return to which(v == b) would be 1, 2, 4. – khtad Jun 26 '20 at 21:33
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

- 3,002
- 2
- 18
- 16
-
8I 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
-
-
-
9The 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
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

- 16,676
- 16
- 93
- 129
-
8As 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
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

- 24,229
- 18
- 37
- 41
-
11Be aware this behaves differently from `%in%`: `any(1==NA)` returns `NA`, where `1 %in% NA` returns `FALSE`. – Mar 23 '17 at 01:34
-
You can use the %in%
operator:
vec <- c(1, 2, 3, 4, 5)
1 %in% vec # true
10 %in% vec # false

- 120,335
- 23
- 147
- 134
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))]
-
`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
-
2Why 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
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.

- 361
- 2
- 9
-
12By 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
-
12Do not use regex for exact matches. This is dangerous and can have unexpected results – David Arenburg Sep 10 '16 at 17:54
-
10Yeah, 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
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)

- 35,235
- 5
- 20
- 53