rguides

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

ParameterTypeDefaultDescription
stringcharacterRequiredA character vector to search
patternpatternRequiredA pattern to look for (regex, fixed, or coll)
regexlogicalTRUEIf 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) and str_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) where pattern_vec is the same length as x matches each string against its corresponding pattern — a powerful technique for record-level matching.