stringr str_detect() in R: Find Pattern in Strings
The str_detect() function in stringr returns TRUE or FALSE for each string indicating whether a pattern was found. It is the modern, vectorized replacement for base R grepl().
str_detect(x, "pattern") # regex (default) str_detect(x, fixed("text")) # literal match str_detect(x, regex("pattern", ignore_case = TRUE)) # case-insensitive str_detect(x, "pattern", negate = TRUE) # opposite (not match) str_detect(c("apple","banana"), "an") # vectorized sum(str_detect(x, "pattern")) # count matches filter(df, str_detect(name, "Smith")) # use in dplyr filter
Need explanation? Read on for examples and pitfalls.
What str_detect() does in one sentence
str_detect(string, pattern) returns a logical vector of the same length as string, with TRUE where the pattern matches and FALSE elsewhere. The pattern is a regular expression by default; wrap with fixed() for literal string matching.
It is the workhorse for filtering data frames by string conditions, validating user input, and pre-processing text data.
Syntax
str_detect(string, pattern, negate = FALSE). Pattern is regex; use modifiers for fixed or case-insensitive.
., use fixed(".") or \\.. To match a literal (, use \\(. The fixed() modifier is the simplest way to skip regex parsing entirely.Five common patterns
1. Basic regex detection
2. Literal (non-regex) match
fixed("text") treats text literally. Without fixed, . is regex for "any character".
3. Case-insensitive match
regex(pattern, ignore_case = TRUE) is the case-insensitive variant.
4. Negate (find non-matches)
negate = TRUE flips the result. Equivalent to !str_detect(...).
5. Use in dplyr filter
str_detect() returns a logical vector, perfect for filter().
str_detect() and grepl() produce the same results for simple patterns. stringr is more consistent (always returns the same length as input, NA in produces NA out) and reads cleaner in pipelines. For large vectors, performance is similar.Common pitfalls
Pitfall 1: regex special chars treated literally. str_detect(x, "1.5") matches "1a5", "1b5", etc., not just "1.5". Use fixed("1.5") or escape: "1\\.5".
Pitfall 2: NA propagation. str_detect(NA, "x") returns NA, not FALSE. Filter with !is.na(x) & str_detect(...) to drop NAs cleanly.
^ and $ match start/end of EACH STRING, not start/end of vector. str_detect(c("apple","banana"), "^a") returns c(TRUE, FALSE). To match whole strings exactly, use ^pattern$.Try it yourself
Try it: Filter iris$Species (as a character vector) to rows where the species name contains "color". Save to ex_match.
Click to reveal solution
Explanation: str_detect(species, "color") returns TRUE for species containing "color" anywhere. species[...] subsets to those entries. Only "versicolor" matches.
Related stringr functions
After mastering str_detect, look at:
str_extract(): pull out the matched substringstr_replace(): replace matched patternstr_count(): count matches per stringstr_locate(): find position of matchstr_subset(): return matching strings (filter + extract in one)grepl(): base R equivalent
For complex patterns, the regex(), fixed(), coll(), and boundary() modifier functions in stringr give precise control over match behavior.
FAQ
How do I check if a string contains a pattern in R?
Use stringr::str_detect(string, "pattern"). Returns TRUE/FALSE per string. The pattern is a regex by default; wrap with fixed() for literal match.
What is the difference between str_detect and grepl in R?
Both return logical vectors. str_detect() is more consistent (NA in -> NA out, predictable lengths). grepl() is base R, no package needed. Choose stringr for tidyverse code; grepl for zero dependencies.
How do I do a case-insensitive str_detect in R?
Wrap the pattern in regex(pattern, ignore_case = TRUE): str_detect(x, regex("apple", ignore_case = TRUE)).
How do I check if a string starts with a substring in R?
Use anchor ^: str_detect(x, "^apple") returns TRUE for strings starting with "apple". Or use str_starts(x, "apple") for a clearer intent.
How do I count strings matching a pattern?
sum(str_detect(x, "pattern")) counts how many of the strings match. To count matches WITHIN each string, use str_count(x, "pattern") instead.