Menu

Strings in R: paste, sprintf, gsub, substr & More

Everything you need for text in R: creating strings, joining with paste and paste0, formatting with sprintf, and searching with gsub, grepl, and strsplit.

This page includes runnable editors - edit, run, and see output instantly.

Creating Strings in R

A string in R is text between quotes. Double and single quotes both work and mean exactly the same thing; the convention is double quotes, switching to single when the text itself contains a double quote:

Backslash escapes work as in most languages: \" for a literal quote, \n for a newline, \t for a tab, \\ for a backslash itself.

Now the mistake every R beginner makes exactly once: asking a string how long it is with length().

nchar() counts characters - 5. length() counts vector elements, and a single string is a vector of one element - so it says 1. In R everything is a vector, including text, and all the functions on this page quietly work element-wise across whole character vectors. That's a feature, once you stop being surprised by it.

Joining Strings: paste() and paste0()

R has no + for strings. Concatenation is paste(), which joins its arguments with a space by default, and paste0(), which joins with nothing:

Because paste is vectorized, giving it a vector builds many strings at once - this is how you generate filenames, labels, and IDs in one line:

And the collapse argument does the opposite: it fuses a whole vector into a single string with a chosen separator:

Remember the split: sep controls the glue between arguments, collapse the glue between elements of one vector. You can use both in one call.

Formatting with sprintf()

When you need numbers formatted inside text - fixed decimal places, padded widths - paste() runs out of steam and sprintf() takes over. It uses C-style format codes: %s for strings, %d for whole numbers, %f for decimals:

%.1f means "one decimal place", %.3f three, and %05d pads to five digits with zeros. A doubled %% produces a literal percent sign. sprintf() is also vectorized, so it can format a whole column of values in one call - see input and output for the sprintf() + cat() reporting pattern.

Changing Case and Slicing: toupper(), tolower(), substr()

Case conversion is exactly what it says:

tolower() earns its keep normalizing messy data before comparison - "Yes", "YES", and "yes" all become the same value.

substr(x, start, stop) extracts a slice by character position, counting from 1 (R is 1-indexed everywhere):

Both endpoints are inclusive: positions 1 through 11 give "Programming".

Find and Replace: sub(), gsub(), and grepl()

sub() replaces the first occurrence of a pattern; gsub() ("global substitute") replaces all of them:

One critical detail: the pattern is a regular expression by default, not literal text. Regex characters like ., *, (, and ? have special meanings - a bare . matches any character. When you mean the literal text, pass fixed = TRUE:

The first line gives a-b-c; the second gives -----, because as a regex . matched every single character. Until you've learned regex, make fixed = TRUE your default and you'll never be bitten.

grepl() doesn't replace - it tests whether each element matches, returning a logical vector. That makes it the standard tool for filtering text:

The first result marks which filenames contain .csv; the second uses that logical vector to keep only the matches.

Splitting and Trimming: strsplit() and trimws()

strsplit() cuts a string apart on a separator. Its one quirk: it returns a list, because it can split many strings at once. For a single string, take the first element with [[1]]:

And trimws() strips the whitespace that real-world data always arrives wrapped in:

By default it trims both ends; which = "left" or "right" trims one side only (the names refer to string start and end).

The stringr Alternative

Everything above is base R - always available, no installation. The tidyverse's stringr package wraps the same operations in a consistent str_* naming scheme with the string always as the first argument, which many people find easier to remember (see packages for installing it):

library(stringr)

str_detect(files, "csv")            # like grepl(), data first
str_replace_all(s, "good", "great") # like gsub(), arguments reordered
str_length("hello")                 # like nchar()

Base R string functions are worth knowing regardless - you'll meet them in every script, Stack Overflow answer, and error message ever written. Learn the base names first; adopt stringr when the inconsistent argument orders start to annoy you.

What You Take Away

  • Strings use double quotes by convention; nchar() counts characters, length() counts vector elements.
  • Concatenate with paste() / paste0(); sep glues arguments, collapse glues a vector into one string.
  • sprintf() handles formatted output: %s, %d, %.2f.
  • sub() replaces the first match, gsub() all matches, grepl() tests for matches - all regex by default, so pass fixed = TRUE for literal text.
  • strsplit() returns a list (grab [[1]]); trimws() cleans padded input.

Next up: getting text in and out of your programs - printing with print() and cat(), and reading user input.

Frequently Asked Questions

How do you concatenate strings in R?

With paste() or paste0() - R has no + for strings. paste("data", "science") gives "data science" (space-separated by default); paste0("data", "science") joins with nothing. Use sep = to change the separator and collapse = to fuse a whole vector into one string.

How do you get the length of a string in R?

nchar("hello") returns 5, the number of characters. length("hello") returns 1 - in R, length() counts elements of a vector, and a single string is a vector of one element. Confusing length() with nchar() is the classic beginner mistake.

What is the difference between sub() and gsub() in R?

Both find and replace, but sub() replaces only the first match while gsub() ("global sub") replaces all matches. Both treat the pattern as a regular expression by default - pass fixed = TRUE to match the literal text instead.

How do you split a string in R?

strsplit(x, split) splits on a pattern, but it returns a list (because it can split many strings at once). For a single string, grab the first element: strsplit("a,b,c", ",")[[1]] gives the character vector "a" "b" "c".

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED