stringr::str_detect()
str_detect(string, pattern, regex = TRUE) The str_detect() function from stringr detects whether a pattern exists within a string. It returns a logical vector indicating which strings contain the match, making it useful for filtering, conditional operations, and subsetting string data.
Syntax
str_detect(string, pattern, regex = TRUE)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
string | character | Required | A character vector to search |
pattern | pattern | Required | A pattern to look for (regex, fixed, or coll) |
regex | logical | TRUE | If TRUE, pattern is interpreted as a regular expression |
Examples
Basic usage
library(stringr)
# Detect a simple substring
strings <- c("apple", "banana", "cherry", "date")
str_detect(strings, "a")
# [1] TRUE TRUE FALSE TRUE
The next example demonstrates using with dplyr filter, building on the pattern established above and showing how the function behaves with a different set of inputs or arguments. Working through these variations step by step reinforces how each parameter affects the output and builds the muscle memory you need to reach for the right function in your own R scripts without having to consult the documentation every time.
Using with dplyr filter
library(dplyr)
fruits <- data.frame(
name = c("apple", "banana", "cherry", "date", "apricot"),
color = c("red", "yellow", "red", "brown", "orange")
)
# Filter rows where name contains "a"
fruits %>% filter(str_detect(name, "a"))
# name color
# 1 apple red
# 2 banana yellow
# 3 apricot orange
The next example demonstrates regex patterns, building on the pattern established above and showing how the function behaves with a different set of inputs or arguments. Working through these variations step by step reinforces how each parameter affects the output and builds the muscle memory you need to reach for the right function in your own R scripts without having to consult the documentation every time.
Regex patterns
# Detect strings starting with "a"
str_detect(c("apple", "banana", "apricot"), "^a")
# [1] TRUE FALSE TRUE
# Detect strings ending with "e"
str_detect(c("apple", "banana", "cherry"), "e$")
# [1] TRUE FALSE TRUE
# Detect strings containing any digit
str_detect(c("abc123", "def", "xyz789"), "\\\\d")
# [1] TRUE FALSE TRUE
The next example demonstrates case-insensitive matching, building on the pattern established above and showing how the function behaves with a different set of inputs or arguments. Working through these variations step by step reinforces how each parameter affects the output and builds the muscle memory you need to reach for the right function in your own R scripts without having to consult the documentation every time.
Case-insensitive matching
# Default is case-sensitive
str_detect("Apple", "apple")
# [1] FALSE
# Use regex with (?i) for case-insensitive
str_detect("Apple", "(?i)apple")
# [1] TRUE
# Or use fixed() for exact matching
str_detect("Apple", fixed("apple", ignore_case = TRUE))
# [1] TRUE
The next example demonstrates detecting multiple patterns, building on the pattern established above and showing how the function behaves with a different set of inputs or arguments. Working through these variations step by step reinforces how each parameter affects the output and builds the muscle memory you need to reach for the right function in your own R scripts without having to consult the documentation every time.
Detecting multiple patterns
# Detect any of multiple patterns using |
str_detect(c("cat", "dog", "bat"), "cat|dog")
# [1] TRUE TRUE FALSE
The next example demonstrates combined with mutate, building on the pattern established above and showing how the function behaves with a different set of inputs or arguments. Working through these variations step by step reinforces how each parameter affects the output and builds the muscle memory you need to reach for the right function in your own R scripts without having to consult the documentation every time.
Common patterns
- With dplyr::mutate: Add a column indicating pattern match
- With dplyr::filter: Subset rows based on string content
- With sum(): Count matching strings
- With which(): Get indices of matching strings
Combined with mutate
library(dplyr)
df <- data.frame(
email = c("user1@example.com", "invalid", "user2@test.org", "another.invalid")
)
df \%>\%
mutate(
is_valid_email = str_detect(email, "@.*\\\\.")
)
# email is_valid_email
# 1 user1@example.com TRUE
# 2 invalid FALSE
# 3 user2@test.org TRUE
# 4 another.invalid FALSE
The next example demonstrates counting matches, building on the pattern established above and showing how the function behaves with a different set of inputs or arguments. Working through these variations step by step reinforces how each parameter affects the output and builds the muscle memory you need to reach for the right function in your own R scripts without having to consult the documentation every time.
Counting matches
strings <- c("apple", "banana", "cherry", "date", "apricot")
# Count how many strings contain "a"
sum(str_detect(strings, "a"))
# [1] 4
stringr::str_detect() in practice
str_detect() returns a logical vector indicating whether each string matches the pattern. It is the stringr equivalent of grepl(), using the same PCRE regex engine. str_detect(x, "pattern") is equivalent to grepl("pattern", x, perl = TRUE).
In dplyr::filter(), str_detect() is the natural way to filter rows by pattern: filter(df, str_detect(text, "keyword")). For negating, use !str_detect(x, pattern) or str_detect(x, negate = TRUE).
str_detect() vectorizes over both string and pattern. When pattern is a vector, each string is tested against the corresponding pattern. any(str_detect(strings, patterns)) tests whether any string matches any pattern. For testing multiple patterns against one string, use any(str_detect(string, c("pat1","pat2"))) or the regex alternation str_detect(string, "pat1|pat2").
fixed("literal", ignore_case=TRUE) wraps a pattern for literal (non-regex) matching with optional case insensitivity. Use fixed() when the pattern contains regex metacharacters that should be matched literally: str_detect(x, fixed("(optional)")) matches the literal string "(optional)" without treating parentheses as regex groups.
str_detect() returns a logical vector the same length as the input, making it ideal for filter(): filter(df, str_detect(col, "pattern")). Pass negate = TRUE to return TRUE for non-matching strings. For vectorized pattern matching against multiple patterns, use str_detect(x, fixed(pattern)) for literal matching without regex interpretation, which is faster and avoids escaping special characters.
Performance and vectorized logic
str_detect() is vectorized over the string argument and returns a logical vector of the same length. Filtering a data frame column with filter(str_detect(col, pattern)) is idiomatic and efficient. For checking whether any string in a vector matches, any(str_detect(strings, pattern)) is clearer than length(grep(pattern, strings)) > 0.
When checking multiple patterns, avoid calling str_detect() multiple times and combining with |. Instead, combine patterns into a single regex with alternation: str_detect(x, "cat|dog|bird") is one call that matches any of the three patterns. For many patterns stored in a vector, collapse them with paste(patterns, collapse = "|") to build the alternation programmatically. This approach is faster than multiple str_detect() calls joined with |.
See also
- dplyr::filter()
- purrr::map()
str_starts(x, pattern)andstr_ends(x, pattern)are optimized variants for anchored prefix and suffix matching.str_detect(x, fixed("literal.text"))performs literal matching without regex interpretation, the dot matches only a period, not any character.str_detect(x, regex("pattern", ignore_case = TRUE))adds flags to the pattern. For vectorized pattern matching where each string has its own pattern,str_detect(x, pattern_vec)wherepattern_vecis the same length asxmatches each string against its corresponding pattern — a powerful technique for record-level matching.