How to check if a vector contains a given value?
%
-signs that is. The word in
is a reserved word in R use in for-loop construction.
select(iris, contains("etal"))
.
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
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
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
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.
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
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
%in%
: any(1==NA)
returns NA
, where 1 %in% NA
returns FALSE
.
any(1==NA, na.rm=TRUE)
returns FALSE
.
You can use the %in%
operator:
vec <- c(1, 2, 3, 4, 5)
1 %in% vec # true
10 %in% vec # false
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 stackoverflow.com/questions/1169388/…
which
if you just want to find the elements not in Tset
? You can just index pop
directly; pop[!pop%in%Tset]
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.
grep
takes a regular expression as its first element, so to do an exact match for "b"
, either use^e$
or add , fixed=TRUE
).
myvar <- 'blah'; grepl('b', myvar, fixed=TRUE)
will return TRUE
even though 'b' is not in myvar
.
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)
Success story sharing
which(v, 'b')
. Mind the order of the arguments.which(v, 'b')
gives me an error message: >Error in which(v, 'b') : argument to 'which' is not logical