Grep in R using OR and NOT - r

I have the following vector in R and I would like to find all the strings containing A's and B's but not the number 2.
vec1<-c("A_cont_1", "A_cont_12", "B_treat_8", "AB_cont_22", "cont_21_Aa")
The following does not work:
grep("A|B|!2", vec1)
It gives me back all the strings:
[1] 1 2 3 4 5
The same is true for this example:
grep("A|B|-2", vec1)
What would be the correct syntax?

You can do this with a fairly simple regular expression:
grep("^[^2]*[AB][^2]*$", vec1)
In words, it means:
^ match the start of the string
[^2]* match anything except "2", zero or more times
[AB] match "A" or "B"
[^2]* match anything except "2", zero or more times
$ match the end of the string

I would use two grep calls:
intersect(grep("A|B",vec1),grep("2",vec1,invert=TRUE))
#[1] 1 3

OP, your attempt is pretty close, try this:
grep('^(A|B|[^2])*$', vec1)

grep generally does not work very well for doing a positive and a negative search in one invocation. You might be able to make it work with a complex regular expression, but you might be better off just doing:
grep '[AB]' somefile.txt | grep -v '2'
The R equivalent of that would be:
grep("2", grep("A|B", vec1, value = T), invert = T)

I extended the answer provided by #eddi. I have tested it in R and it works for me. I changed the last variable in your example since they all contained A|B.
# Create the vector from the OP with one change
vec1<-c("A_cont_1", "A_cont_12", "B_treat_8", "AB_cont_22", "cont_21_dd")
I then ran the following code. It will tell you which results you should expect from each section of grep.
First, tell me which columns contain A or B
> grepl("A|B", vec1)
[1] TRUE TRUE TRUE TRUE FALSE
Now tell me which columns contain a "2"
> grepl("2", vec1)
[1] FALSE TRUE FALSE TRUE TRUE
The index we want is 2,4
> grep("2", grep("A|B", vec1, value = T))
[1] 2 4
Done!

Related

Concatenating R strings with a separator - except the first time

I have a process that does a few checks to a data frame, and at each check if the check passes I want to add a text to a column with a separator. So suppose after the first test rows 2 and 3 pass, so the msg column has "first" in it. Then the second test updated the ok column and is true for rows 1 and 2, giving the following:
> d = data.frame(ok=c(TRUE,TRUE,FALSE,FALSE), msg=c("", "first","first",""))
> d
ok msg
1 TRUE
2 TRUE first
3 FALSE first
4 FALSE
so the next step would be to add "second" to the msg column in rows 1 and 2 only, resulting in:
ok msg
1 TRUE second
2 TRUE first;second
3 FALSE first
4 FALSE
I can't work out how to do it. This first effort leaves a leading separator in the initial case:
> paste(d$msg[d$ok],"second", sep=";")
[1] ";second" "first;second"
This returns a length-3 vector which is clearly wrong:
> paste(c(d$msg[d$ok],"second"), sep=";")
[1] "" "first" "second"
and anything with collapse returns a length-1 vector which is also wrong.
Sledgehammer solution is to use the first effort above and then strip any leading separators at the end, but that's ugly. I'm hoping for something neater.
Solutions should only use base R functions, and the initial "empty string" doesn't have to be "" - but I've played with NA and got nowhere. A solution neater (in my opinion) than my sledgehammer will get accepted.
Using your dataframe d, we can use a base ifelse function to get around your problems with separators:
d$msg <- as.character(d$msg)
d$msg[d$ok] <- ifelse(d$msg[d$ok] == "", "second", paste(d$msg[d$ok], "second", sep=";"))
Output:
ok msg
1 TRUE second
2 TRUE first;second
3 FALSE first
4 FALSE
You can write a function which tests the cases of an empty string:
strAppend <- function(a, b, sep=";") {
paste0(a, c("", sep)[1+nchar(a)>0], b)
# paste0(a, c(sep,"")[1+(a=="")], b) #Alternative
}
strAppend(d$msg[d$ok], "second")
#[1] "second" "first;second"

How to identify row using part of a factor of a column [duplicate]

I'm trying to determine if a string is a subset of another string. For example:
chars <- "test"
value <- "es"
I want to return TRUE if "value" appears as part of the string "chars". In the following scenario, I would want to return false:
chars <- "test"
value <- "et"
Use the grepl function
grepl( needle, haystack, fixed = TRUE)
like so:
grepl(value, chars, fixed = TRUE)
# TRUE
Use ?grepl to find out more.
Answer
Sigh, it took me 45 minutes to find the answer to this simple question. The answer is: grepl(needle, haystack, fixed=TRUE)
# Correct
> grepl("1+2", "1+2", fixed=TRUE)
[1] TRUE
> grepl("1+2", "123+456", fixed=TRUE)
[1] FALSE
# Incorrect
> grepl("1+2", "1+2")
[1] FALSE
> grepl("1+2", "123+456")
[1] TRUE
Interpretation
grep is named after the linux executable, which is itself an acronym of "Global Regular Expression Print", it would read lines of input and then print them if they matched the arguments you gave. "Global" meant the match could occur anywhere on the input line, I'll explain "Regular Expression" below, but the idea is it's a smarter way to match the string (R calls this "character", eg class("abc")), and "Print" because it's a command line program, emitting output means it prints to its output string.
Now, the grep program is basically a filter, from lines of input, to lines of output. And it seems that R's grep function similarly will take an array of inputs. For reasons that are utterly unknown to me (I only started playing with R about an hour ago), it returns a vector of the indexes that match, rather than a list of matches.
But, back to your original question, what we really want is to know whether we found the needle in the haystack, a true/false value. They apparently decided to name this function grepl, as in "grep" but with a "Logical" return value (they call true and false logical values, eg class(TRUE)).
So, now we know where the name came from and what it's supposed to do. Lets get back to Regular Expressions. The arguments, even though they are strings, they are used to build regular expressions (henceforth: regex). A regex is a way to match a string (if this definition irritates you, let it go). For example, the regex a matches the character "a", the regex a* matches the character "a" 0 or more times, and the regex a+ would match the character "a" 1 or more times. Hence in the example above, the needle we are searching for 1+2, when treated as a regex, means "one or more 1 followed by a 2"... but ours is followed by a plus!
So, if you used the grepl without setting fixed, your needles would accidentally be haystacks, and that would accidentally work quite often, we can see it even works for the OP's example. But that's a latent bug! We need to tell it the input is a string, not a regex, which is apparently what fixed is for. Why fixed? No clue, bookmark this answer b/c you're probably going to have to look it up 5 more times before you get it memorized.
A few final thoughts
The better your code is, the less history you have to know to make sense of it. Every argument can have at least two interesting values (otherwise it wouldn't need to be an argument), the docs list 9 arguments here, which means there's at least 2^9=512 ways to invoke it, that's a lot of work to write, test, and remember... decouple such functions (split them up, remove dependencies on each other, string things are different than regex things are different than vector things). Some of the options are also mutually exclusive, don't give users incorrect ways to use the code, ie the problematic invocation should be structurally nonsensical (such as passing an option that doesn't exist), not logically nonsensical (where you have to emit a warning to explain it). Put metaphorically: replacing the front door in the side of the 10th floor with a wall is better than hanging a sign that warns against its use, but either is better than neither. In an interface, the function defines what the arguments should look like, not the caller (because the caller depends on the function, inferring everything that everyone might ever want to call it with makes the function depend on the callers, too, and this type of cyclical dependency will quickly clog a system up and never provide the benefits you expect). Be very wary of equivocating types, it's a design flaw that things like TRUE and 0 and "abc" are all vectors.
You want grepl:
> chars <- "test"
> value <- "es"
> grepl(value, chars)
[1] TRUE
> chars <- "test"
> value <- "et"
> grepl(value, chars)
[1] FALSE
Also, can be done using "stringr" library:
> library(stringr)
> chars <- "test"
> value <- "es"
> str_detect(chars, value)
[1] TRUE
### For multiple value case:
> value <- c("es", "l", "est", "a", "test")
> str_detect(chars, value)
[1] TRUE FALSE TRUE FALSE TRUE
Use this function from stringi package:
> stri_detect_fixed("test",c("et","es"))
[1] FALSE TRUE
Some benchmarks:
library(stringi)
set.seed(123L)
value <- stri_rand_strings(10000, ceiling(runif(10000, 1, 100))) # 10000 random ASCII strings
head(value)
chars <- "es"
library(microbenchmark)
microbenchmark(
grepl(chars, value),
grepl(chars, value, fixed=TRUE),
grepl(chars, value, perl=TRUE),
stri_detect_fixed(value, chars),
stri_detect_regex(value, chars)
)
## Unit: milliseconds
## expr min lq median uq max neval
## grepl(chars, value) 13.682876 13.943184 14.057991 14.295423 15.443530 100
## grepl(chars, value, fixed = TRUE) 5.071617 5.110779 5.281498 5.523421 45.243791 100
## grepl(chars, value, perl = TRUE) 1.835558 1.873280 1.956974 2.259203 3.506741 100
## stri_detect_fixed(value, chars) 1.191403 1.233287 1.309720 1.510677 2.821284 100
## stri_detect_regex(value, chars) 6.043537 6.154198 6.273506 6.447714 7.884380 100
Just in case you would also like check if a string (or a set of strings) contain(s) multiple sub-strings, you can also use the '|' between two substrings.
>substring="as|at"
>string_vector=c("ass","ear","eye","heat")
>grepl(substring,string_vector)
You will get
[1] TRUE FALSE FALSE TRUE
since the 1st word has substring "as", and the last word contains substring "at"
Use grep or grepl but be aware of whether or not you want to use regular expressions.
By default, grep and related take a regular expression to match, not a literal substring. If you're not expecting that, and you try to match on an invalid regex, it doesn't work:
> grep("[", "abc[")
Error in grep("[", "abc[") :
invalid regular expression '[', reason 'Missing ']''
To do a true substring test, use fixed = TRUE.
> grep("[", "abc[", fixed = TRUE)
[1] 1
If you do want regex, great, but that's not what the OP appears to be asking.
You can use grep
grep("es", "Test")
[1] 1
grep("et", "Test")
integer(0)
Similar problem here: Given a string and a list of keywords, detect which, if any, of the keywords are contained in the string.
Recommendations from this thread suggest stringr's str_detect and grepl. Here are the benchmarks from the microbenchmark package:
Using
map_keywords = c("once", "twice", "few")
t = "yes but only a few times"
mapper1 <- function (x) {
r = str_detect(x, map_keywords)
}
mapper2 <- function (x) {
r = sapply(map_keywords, function (k) grepl(k, x, fixed = T))
}
and then
microbenchmark(mapper1(t), mapper2(t), times = 5000)
we find
Unit: microseconds
expr min lq mean median uq max neval
mapper1(t) 26.401 27.988 31.32951 28.8430 29.5225 2091.476 5000
mapper2(t) 19.289 20.767 24.94484 23.7725 24.6220 1011.837 5000
As you can see, over 5,000 iterations of the keyword search using str_detect and grepl over a practical string and vector of keywords, grepl performs quite a bit better than str_detect.
The outcome is the boolean vector r which identifies which, if any, of the keywords are contained in the string.
Therefore, I recommend using grepl to determine if any keywords are in a string.

How check if string contain a particular number? [duplicate]

I'm trying to determine if a string is a subset of another string. For example:
chars <- "test"
value <- "es"
I want to return TRUE if "value" appears as part of the string "chars". In the following scenario, I would want to return false:
chars <- "test"
value <- "et"
Use the grepl function
grepl( needle, haystack, fixed = TRUE)
like so:
grepl(value, chars, fixed = TRUE)
# TRUE
Use ?grepl to find out more.
Answer
Sigh, it took me 45 minutes to find the answer to this simple question. The answer is: grepl(needle, haystack, fixed=TRUE)
# Correct
> grepl("1+2", "1+2", fixed=TRUE)
[1] TRUE
> grepl("1+2", "123+456", fixed=TRUE)
[1] FALSE
# Incorrect
> grepl("1+2", "1+2")
[1] FALSE
> grepl("1+2", "123+456")
[1] TRUE
Interpretation
grep is named after the linux executable, which is itself an acronym of "Global Regular Expression Print", it would read lines of input and then print them if they matched the arguments you gave. "Global" meant the match could occur anywhere on the input line, I'll explain "Regular Expression" below, but the idea is it's a smarter way to match the string (R calls this "character", eg class("abc")), and "Print" because it's a command line program, emitting output means it prints to its output string.
Now, the grep program is basically a filter, from lines of input, to lines of output. And it seems that R's grep function similarly will take an array of inputs. For reasons that are utterly unknown to me (I only started playing with R about an hour ago), it returns a vector of the indexes that match, rather than a list of matches.
But, back to your original question, what we really want is to know whether we found the needle in the haystack, a true/false value. They apparently decided to name this function grepl, as in "grep" but with a "Logical" return value (they call true and false logical values, eg class(TRUE)).
So, now we know where the name came from and what it's supposed to do. Lets get back to Regular Expressions. The arguments, even though they are strings, they are used to build regular expressions (henceforth: regex). A regex is a way to match a string (if this definition irritates you, let it go). For example, the regex a matches the character "a", the regex a* matches the character "a" 0 or more times, and the regex a+ would match the character "a" 1 or more times. Hence in the example above, the needle we are searching for 1+2, when treated as a regex, means "one or more 1 followed by a 2"... but ours is followed by a plus!
So, if you used the grepl without setting fixed, your needles would accidentally be haystacks, and that would accidentally work quite often, we can see it even works for the OP's example. But that's a latent bug! We need to tell it the input is a string, not a regex, which is apparently what fixed is for. Why fixed? No clue, bookmark this answer b/c you're probably going to have to look it up 5 more times before you get it memorized.
A few final thoughts
The better your code is, the less history you have to know to make sense of it. Every argument can have at least two interesting values (otherwise it wouldn't need to be an argument), the docs list 9 arguments here, which means there's at least 2^9=512 ways to invoke it, that's a lot of work to write, test, and remember... decouple such functions (split them up, remove dependencies on each other, string things are different than regex things are different than vector things). Some of the options are also mutually exclusive, don't give users incorrect ways to use the code, ie the problematic invocation should be structurally nonsensical (such as passing an option that doesn't exist), not logically nonsensical (where you have to emit a warning to explain it). Put metaphorically: replacing the front door in the side of the 10th floor with a wall is better than hanging a sign that warns against its use, but either is better than neither. In an interface, the function defines what the arguments should look like, not the caller (because the caller depends on the function, inferring everything that everyone might ever want to call it with makes the function depend on the callers, too, and this type of cyclical dependency will quickly clog a system up and never provide the benefits you expect). Be very wary of equivocating types, it's a design flaw that things like TRUE and 0 and "abc" are all vectors.
You want grepl:
> chars <- "test"
> value <- "es"
> grepl(value, chars)
[1] TRUE
> chars <- "test"
> value <- "et"
> grepl(value, chars)
[1] FALSE
Also, can be done using "stringr" library:
> library(stringr)
> chars <- "test"
> value <- "es"
> str_detect(chars, value)
[1] TRUE
### For multiple value case:
> value <- c("es", "l", "est", "a", "test")
> str_detect(chars, value)
[1] TRUE FALSE TRUE FALSE TRUE
Use this function from stringi package:
> stri_detect_fixed("test",c("et","es"))
[1] FALSE TRUE
Some benchmarks:
library(stringi)
set.seed(123L)
value <- stri_rand_strings(10000, ceiling(runif(10000, 1, 100))) # 10000 random ASCII strings
head(value)
chars <- "es"
library(microbenchmark)
microbenchmark(
grepl(chars, value),
grepl(chars, value, fixed=TRUE),
grepl(chars, value, perl=TRUE),
stri_detect_fixed(value, chars),
stri_detect_regex(value, chars)
)
## Unit: milliseconds
## expr min lq median uq max neval
## grepl(chars, value) 13.682876 13.943184 14.057991 14.295423 15.443530 100
## grepl(chars, value, fixed = TRUE) 5.071617 5.110779 5.281498 5.523421 45.243791 100
## grepl(chars, value, perl = TRUE) 1.835558 1.873280 1.956974 2.259203 3.506741 100
## stri_detect_fixed(value, chars) 1.191403 1.233287 1.309720 1.510677 2.821284 100
## stri_detect_regex(value, chars) 6.043537 6.154198 6.273506 6.447714 7.884380 100
Just in case you would also like check if a string (or a set of strings) contain(s) multiple sub-strings, you can also use the '|' between two substrings.
>substring="as|at"
>string_vector=c("ass","ear","eye","heat")
>grepl(substring,string_vector)
You will get
[1] TRUE FALSE FALSE TRUE
since the 1st word has substring "as", and the last word contains substring "at"
Use grep or grepl but be aware of whether or not you want to use regular expressions.
By default, grep and related take a regular expression to match, not a literal substring. If you're not expecting that, and you try to match on an invalid regex, it doesn't work:
> grep("[", "abc[")
Error in grep("[", "abc[") :
invalid regular expression '[', reason 'Missing ']''
To do a true substring test, use fixed = TRUE.
> grep("[", "abc[", fixed = TRUE)
[1] 1
If you do want regex, great, but that's not what the OP appears to be asking.
You can use grep
grep("es", "Test")
[1] 1
grep("et", "Test")
integer(0)
Similar problem here: Given a string and a list of keywords, detect which, if any, of the keywords are contained in the string.
Recommendations from this thread suggest stringr's str_detect and grepl. Here are the benchmarks from the microbenchmark package:
Using
map_keywords = c("once", "twice", "few")
t = "yes but only a few times"
mapper1 <- function (x) {
r = str_detect(x, map_keywords)
}
mapper2 <- function (x) {
r = sapply(map_keywords, function (k) grepl(k, x, fixed = T))
}
and then
microbenchmark(mapper1(t), mapper2(t), times = 5000)
we find
Unit: microseconds
expr min lq mean median uq max neval
mapper1(t) 26.401 27.988 31.32951 28.8430 29.5225 2091.476 5000
mapper2(t) 19.289 20.767 24.94484 23.7725 24.6220 1011.837 5000
As you can see, over 5,000 iterations of the keyword search using str_detect and grepl over a practical string and vector of keywords, grepl performs quite a bit better than str_detect.
The outcome is the boolean vector r which identifies which, if any, of the keywords are contained in the string.
Therefore, I recommend using grepl to determine if any keywords are in a string.

How can I check if multiple strings exist in another string?

I have this string:
myStr <- "I am very beautiful btw"
str <- c("very","beauti","bt")
Now I want to check whether myStr includes all strings in str, how can I do this in R? For example above it should be TRUE.
Many Thanks
Yes, you can use grepl (not grep, actually), but you must run it once for each substring:
> sapply(str, grepl, myStr)
very beauti bt
TRUE TRUE TRUE
To get only one result if all of them are true, use all:
> all(sapply(str, grepl, myStr))
[1] TRUE
Edit:
In case you have more than one string to check, say:
myStrings <- c("I am very beautiful btw", "I am not beautiful btw")
You then run the sapply code, which will return a matrix with one row for each string in myStrings. Apply all on each row:
> apply(sapply(str, grepl, myStrings), 1, all)
[1] TRUE FALSE
Using stringr you could do:
str_detect(myStr, str)
Which returns a result for each substring:
#[1] TRUE TRUE TRUE
Or as per #thelatemail suggestion, if you want to know if all of them are true:
all(str_detect(myStr,str))
Which gives:
#[1] TRUE
You could also find the location (start, end) of every character in myStr that matches str
str_locate(myStr, str)
Which gives:
# start end
#[1,] 6 9
#[2,] 11 16
#[3,] 21 22

Test if characters are in a string

I'm trying to determine if a string is a subset of another string. For example:
chars <- "test"
value <- "es"
I want to return TRUE if "value" appears as part of the string "chars". In the following scenario, I would want to return false:
chars <- "test"
value <- "et"
Use the grepl function
grepl( needle, haystack, fixed = TRUE)
like so:
grepl(value, chars, fixed = TRUE)
# TRUE
Use ?grepl to find out more.
Answer
Sigh, it took me 45 minutes to find the answer to this simple question. The answer is: grepl(needle, haystack, fixed=TRUE)
# Correct
> grepl("1+2", "1+2", fixed=TRUE)
[1] TRUE
> grepl("1+2", "123+456", fixed=TRUE)
[1] FALSE
# Incorrect
> grepl("1+2", "1+2")
[1] FALSE
> grepl("1+2", "123+456")
[1] TRUE
Interpretation
grep is named after the linux executable, which is itself an acronym of "Global Regular Expression Print", it would read lines of input and then print them if they matched the arguments you gave. "Global" meant the match could occur anywhere on the input line, I'll explain "Regular Expression" below, but the idea is it's a smarter way to match the string (R calls this "character", eg class("abc")), and "Print" because it's a command line program, emitting output means it prints to its output string.
Now, the grep program is basically a filter, from lines of input, to lines of output. And it seems that R's grep function similarly will take an array of inputs. For reasons that are utterly unknown to me (I only started playing with R about an hour ago), it returns a vector of the indexes that match, rather than a list of matches.
But, back to your original question, what we really want is to know whether we found the needle in the haystack, a true/false value. They apparently decided to name this function grepl, as in "grep" but with a "Logical" return value (they call true and false logical values, eg class(TRUE)).
So, now we know where the name came from and what it's supposed to do. Lets get back to Regular Expressions. The arguments, even though they are strings, they are used to build regular expressions (henceforth: regex). A regex is a way to match a string (if this definition irritates you, let it go). For example, the regex a matches the character "a", the regex a* matches the character "a" 0 or more times, and the regex a+ would match the character "a" 1 or more times. Hence in the example above, the needle we are searching for 1+2, when treated as a regex, means "one or more 1 followed by a 2"... but ours is followed by a plus!
So, if you used the grepl without setting fixed, your needles would accidentally be haystacks, and that would accidentally work quite often, we can see it even works for the OP's example. But that's a latent bug! We need to tell it the input is a string, not a regex, which is apparently what fixed is for. Why fixed? No clue, bookmark this answer b/c you're probably going to have to look it up 5 more times before you get it memorized.
A few final thoughts
The better your code is, the less history you have to know to make sense of it. Every argument can have at least two interesting values (otherwise it wouldn't need to be an argument), the docs list 9 arguments here, which means there's at least 2^9=512 ways to invoke it, that's a lot of work to write, test, and remember... decouple such functions (split them up, remove dependencies on each other, string things are different than regex things are different than vector things). Some of the options are also mutually exclusive, don't give users incorrect ways to use the code, ie the problematic invocation should be structurally nonsensical (such as passing an option that doesn't exist), not logically nonsensical (where you have to emit a warning to explain it). Put metaphorically: replacing the front door in the side of the 10th floor with a wall is better than hanging a sign that warns against its use, but either is better than neither. In an interface, the function defines what the arguments should look like, not the caller (because the caller depends on the function, inferring everything that everyone might ever want to call it with makes the function depend on the callers, too, and this type of cyclical dependency will quickly clog a system up and never provide the benefits you expect). Be very wary of equivocating types, it's a design flaw that things like TRUE and 0 and "abc" are all vectors.
You want grepl:
> chars <- "test"
> value <- "es"
> grepl(value, chars)
[1] TRUE
> chars <- "test"
> value <- "et"
> grepl(value, chars)
[1] FALSE
Also, can be done using "stringr" library:
> library(stringr)
> chars <- "test"
> value <- "es"
> str_detect(chars, value)
[1] TRUE
### For multiple value case:
> value <- c("es", "l", "est", "a", "test")
> str_detect(chars, value)
[1] TRUE FALSE TRUE FALSE TRUE
Use this function from stringi package:
> stri_detect_fixed("test",c("et","es"))
[1] FALSE TRUE
Some benchmarks:
library(stringi)
set.seed(123L)
value <- stri_rand_strings(10000, ceiling(runif(10000, 1, 100))) # 10000 random ASCII strings
head(value)
chars <- "es"
library(microbenchmark)
microbenchmark(
grepl(chars, value),
grepl(chars, value, fixed=TRUE),
grepl(chars, value, perl=TRUE),
stri_detect_fixed(value, chars),
stri_detect_regex(value, chars)
)
## Unit: milliseconds
## expr min lq median uq max neval
## grepl(chars, value) 13.682876 13.943184 14.057991 14.295423 15.443530 100
## grepl(chars, value, fixed = TRUE) 5.071617 5.110779 5.281498 5.523421 45.243791 100
## grepl(chars, value, perl = TRUE) 1.835558 1.873280 1.956974 2.259203 3.506741 100
## stri_detect_fixed(value, chars) 1.191403 1.233287 1.309720 1.510677 2.821284 100
## stri_detect_regex(value, chars) 6.043537 6.154198 6.273506 6.447714 7.884380 100
Just in case you would also like check if a string (or a set of strings) contain(s) multiple sub-strings, you can also use the '|' between two substrings.
>substring="as|at"
>string_vector=c("ass","ear","eye","heat")
>grepl(substring,string_vector)
You will get
[1] TRUE FALSE FALSE TRUE
since the 1st word has substring "as", and the last word contains substring "at"
Use grep or grepl but be aware of whether or not you want to use regular expressions.
By default, grep and related take a regular expression to match, not a literal substring. If you're not expecting that, and you try to match on an invalid regex, it doesn't work:
> grep("[", "abc[")
Error in grep("[", "abc[") :
invalid regular expression '[', reason 'Missing ']''
To do a true substring test, use fixed = TRUE.
> grep("[", "abc[", fixed = TRUE)
[1] 1
If you do want regex, great, but that's not what the OP appears to be asking.
You can use grep
grep("es", "Test")
[1] 1
grep("et", "Test")
integer(0)
Similar problem here: Given a string and a list of keywords, detect which, if any, of the keywords are contained in the string.
Recommendations from this thread suggest stringr's str_detect and grepl. Here are the benchmarks from the microbenchmark package:
Using
map_keywords = c("once", "twice", "few")
t = "yes but only a few times"
mapper1 <- function (x) {
r = str_detect(x, map_keywords)
}
mapper2 <- function (x) {
r = sapply(map_keywords, function (k) grepl(k, x, fixed = T))
}
and then
microbenchmark(mapper1(t), mapper2(t), times = 5000)
we find
Unit: microseconds
expr min lq mean median uq max neval
mapper1(t) 26.401 27.988 31.32951 28.8430 29.5225 2091.476 5000
mapper2(t) 19.289 20.767 24.94484 23.7725 24.6220 1011.837 5000
As you can see, over 5,000 iterations of the keyword search using str_detect and grepl over a practical string and vector of keywords, grepl performs quite a bit better than str_detect.
The outcome is the boolean vector r which identifies which, if any, of the keywords are contained in the string.
Therefore, I recommend using grepl to determine if any keywords are in a string.

Resources