ChatGPT解决这个技术问题 Extra ChatGPT

Test if a vector contains a given element

How to check if a vector contains a given value?

sometimes I ask myself why R just doesn't use the word contains to make it users easier
consider that "in" is contained in "conta(in)s"; I'd contend that "in" is a considerably concise contender in this context
Perhaps with the addition of flanking %-signs that is. The word in is a reserved word in R use in for-loop construction.
@greg121 dplyr already has a contains function, but it's used for a different purpose: to select a column in a data frame. For example select(iris, contains("etal")).
Is there a concise way to do it for real valued numbers with a given precision?

C
Community

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

what about getting all appearances, not just the first one?
Maybe I come a little late. which(v, 'b'). Mind the order of the arguments.
Your which(v, 'b') gives me an error message: >Error in which(v, 'b') : argument to 'which' is not logical
The 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.
J
Justin Nafe

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

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 : Could you give an example of this?
@pomber is it fixed?
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.
i
ishandutta2007

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


As already commented here and here, don't use grep() or regular expressions to find exact matches.
D
Dan Goldstein

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

Be aware this behaves differently from %in%: any(1==NA) returns NA, where 1 %in% NA returns FALSE.
@user3603486: any(1==NA, na.rm=TRUE) returns FALSE.
a
ars

You can use the %in% operator:

vec <- c(1, 2, 3, 4, 5)
1 %in% vec # true
10 %in% vec # false

a
ah bon

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/…
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]
o
ojdajuiceman

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.


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).
Do not use regex for exact matches. This is dangerous and can have unexpected results
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.
Q
Quinten

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)