paste() and paste0() in R: Concatenate Strings
The paste() and paste0() functions in base R combine strings or vectors into a single string or character vector. paste0 is a shortcut for paste(..., sep = "").
paste("Hello", "world") # "Hello world" (default sep = " ")
paste0("Hello", "world") # "Helloworld" (no separator)
paste("a", "b", sep = "-") # "a-b"
paste(c("a","b","c"), collapse = ",") # "a,b,c" (one string)
paste(c("a","b"), c("1","2"), sep = "_") # vectorized: "a_1" "b_2"
paste(c("a","b"), c("1","2"), collapse = "-") # "a 1-b 2"
sprintf("%s is %d", "Alice", 30) # alternative for templatingNeed explanation? Read on for examples and pitfalls.
What paste() does in one sentence
paste(...) takes any number of strings or vectors and combines them, controlled by sep (between inputs) and collapse (between elements of the result vector). Without collapse, the output is a vector; with collapse, the result is a single string.
This is the most-used string concatenation function in base R. Every R programmer learns it early. paste0() is the no-separator shortcut.
Syntax
paste(..., sep = " ", collapse = NULL). Variadic arguments are recycled to the longest length.
paste0() is paste(..., sep = "") and is FASTER for the common no-separator case. Reach for paste0 when you do not need a separator. Use paste with sep when you do.Five common patterns
1. Two strings into one
2. Custom separator
3. Vectorized concatenation
Pairs of elements are joined. Recycling rules apply if the lengths differ.
4. Collapse vector to single string
collapse = ", " joins all elements of the result with the specified separator into ONE string.
5. Combine sep and collapse
sep joins INPUT vectors element-wise. collapse joins the resulting vector into one string.
sep is for COMBINING multiple INPUTS. collapse is for COMBINING the RESULT VECTOR into one string. They serve different purposes. Both can be used together; if neither is set (or only sep), the result is a vector.paste() vs sprintf() vs glue::glue() vs str_c()
Four ways to build strings in R, each with different strengths.
| Function | Best for | Performance | Readability |
|---|---|---|---|
paste() / paste0() |
Simple concatenation | Fast | OK |
sprintf() |
Format with placeholders | Fast | OK for short |
glue::glue() |
Templates with variable interpolation | Medium | Best for complex |
stringr::str_c() |
Tidyverse style | Fast | Cleaner NA behavior |
When to use which:
- Use
paste0for simple "join these strings". - Use
sprintffor fixed-width / formatted output. - Use
gluewhen you embed variables in long template strings. - Use
str_cif you need predictable NA behavior in tidyverse pipelines.
Common pitfalls
Pitfall 1: paste with NA propagates. paste("Alice", NA) returns "Alice NA" (the NA is converted to "NA"). Use str_c() or filter NAs first if this is wrong.
Pitfall 2: forgetting collapse. paste(c("a","b")) returns the SAME vector unchanged (length 2). To get a single string, add collapse = "".
paste("x", 5) returns "x 5", not an error. This is usually fine but sometimes hides bugs (e.g., paste("x", NULL) returns "x" silently because NULL has length 0).Try it yourself
Try it: Build file names like report_2024.csv, report_2025.csv, report_2026.csv from a years vector. Save to ex_files.
Click to reveal solution
Explanation: paste0 with no separator joins "report_", each year, and ".csv" element-wise. Result is a 3-element character vector.
Related string functions
After mastering paste, look at:
sprintf(): format with %s, %d, %f, etc.glue::glue(): template-based interpolation ({var}syntax)stringr::str_c(): stringr's vectorized concatenationformat(): format numbers with specific width and digitsfile.path(): build file paths with the right OS separatortidyr::unite(): data frame column-wise paste
For embedding variables in long template strings, glue("Hello {name}, you are {age}") is much cleaner than paste0.
FAQ
What is the difference between paste and paste0 in R?
paste0(...) is paste(..., sep = ""): it concatenates with NO separator. paste(...) defaults to sep = " ". Use paste0 when you do not want a space (or any separator); paste with sep otherwise.
How do I concatenate strings in R?
paste0("Hello", "world") for no separator. paste("Hello", "world", sep = "-") for a custom separator. For collapsing a vector to one string: paste(c("a","b"), collapse = "-").
What is the difference between sep and collapse in paste?
sep joins MULTIPLE INPUTS element-wise (e.g., paste(c("a","b"), c("1","2"), sep = "_") returns c("a_1","b_2")). collapse joins the RESULT VECTOR into a single string (e.g., paste(..., collapse = ",") returns "a,b").
How do I paste with formatting like sprintf?
Use sprintf("%s is %d years old", name, age) for formatted output. paste does not interpolate variables into a template the way sprintf does.
Why does paste with NA produce "NA"?
paste converts every input to character; as.character(NA) is "NA" (the string). To skip NAs, use stringr::str_c() (returns NA when any input is NA) or filter NAs before pasting.