Strings & Dates

Reviewed & published by Brayan K

Strings and dates are how R handles text and time — cleaning, joining, and searching text, and parsing real dates so you can do arithmetic and extract parts like the year or weekday.

Part of the free R course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

By the end of this lesson you'll manipulate text with paste(), substr(), and case functions, find and replace patterns with grepl() and gsub(), and parse and format real dates with as.Date() and format().

What You'll Learn in This Lesson

1️⃣ Working with Strings

Base R covers the essentials: nchar() for length, toupper()/tolower() for case, trimws() to strip spaces, paste()/paste0() to join, and substr() to slice. All are vectorized.

# Base R has solid string functions, all vectorized.

x <- "  Hello, World  "

nchar(x)             # length incl. spaces -> [1] 16
toupper("abc")       # -> [1] "ABC"
trimws(x)            # trim surrounding spaces -> [1] "Hello, World"

# paste() joins; paste0() joins with no separator:
paste("R", "is", "fun")        # -> [1] "R is fun"
paste0("file", 1:3, ".csv")    # vectorized -> [1] "file1.csv" "file2.csv" "file3.csv"

# substr() slices by position:
substr("programming", 1, 4)    # -> [1] "prog"

2️⃣ Finding and Replacing Patterns

grepl() tests which strings contain a pattern; sub() replaces the first match and gsub() replaces all; strsplit() breaks a string apart. These accept plain text or regular expressions.

# Find and replace patterns. These accept simple text or regex.

emails <- c("a@x.com", "bad-email", "c@y.org")

grepl("@", emails)            # which contain @? -> [1]  TRUE FALSE  TRUE
sub("com", "net", "a@x.com") # replace FIRST match -> [1] "a@x.net"
gsub("o", "0", "foo boo")    # replace ALL matches -> [1] "f00 b00"

# strsplit() breaks a string into pieces:
strsplit("2024-01-15", "-")  # -> list of "2024" "01" "15"

3️⃣ Real Dates

as.Date() turns text into a proper Date you can do arithmetic on (in days). format() extracts and reformats parts, and weekdays() names the day.

# Dates are a real type in R. as.Date() parses "YYYY-MM-DD" by default.

d <- as.Date("2024-03-15")
class(d)             # -> [1] "Date"

# Date arithmetic works in DAYS:
d + 30               # 30 days later -> [1] "2024-04-14"
as.Date("2024-06-01") - d   # days between two dates

# Extract parts and reformat with format():
format(d, "%Y")      # year  -> [1] "2024"
format(d, "%B %d")   # month name + day -> [1] "March 15"
weekdays(d)          # -> [1] "Friday"

Your turn. Fill in the ___ blank, run it, and compare with the expected output.

# 🎯 YOUR TURN — replace each ___ then run it.

names <- c("  ada  ", "BOB", "Cara ")

# 1) Clean each name: trim spaces, then make Title-like (just upper here)
clean <- toupper(trimws(names))
print(clean)

# 2) Build filenames like "ADA.txt" using paste0()
files <- ___(clean, ".txt")   # 👉 replace ___ with paste0
print(files)

# ✅ Expected output:
# [1] "ADA"  "BOB"  "CARA"
# [1] "ADA.txt"  "BOB.txt"  "CARA.txt"

Mini-Challenge: Date Arithmetic

Write it from the outline, run it, and check it against the example output. Subtracting two Dates gives a time difference — wrap it in as.numeric() for a plain number of days.

# 🎯 MINI-CHALLENGE: parse and analyse dates.
#
# Given two date strings:
#   start <- as.Date("2024-01-01")
#   end   <- as.Date("2024-03-10")
#
# 1. Print the number of days between them
#    (hint: as.numeric(end - start)).
# 2. Print the weekday name of 'end' with weekdays().
# 3. Print 'end' formatted as "Month Day, Year"
#    using format(end, "%B %d, %Y").
#
# ✅ Example output:
#    Days: 69
#    End weekday: Sunday
#    Pretty: March 10, 2024

# your code here

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — Strings & Dates

TaskR Syntax
Join stringspaste0(a, b)
Trim / casetrimws(x) ; toupper(x)
Contains pattern?grepl("@", x)
Replace allgsub("a", "b", x)
Parse a dateas.Date("2024-03-15")
Format a dateformat(d, "%Y-%m")

🎉 Lesson Complete!

Practice quiz

Which function joins strings with NO separator?

  • paste()
  • paste0()
  • cat()
  • join()

Answer: paste0(). paste0() concatenates with no separator; paste() uses a space by default.

What does nchar('Hello') return?

  • 5
  • 1
  • "Hello"
  • 0

Answer: 5. nchar() counts the number of characters, including spaces.

Which function strips surrounding whitespace from a string?

  • toupper()
  • trimws()
  • substr()
  • gsub()

Answer: trimws(). trimws() removes leading and trailing whitespace.

What does substr('programming', 1, 4) return?

  • "ming"
  • "gram"
  • "prog"
  • "prgm"

Answer: "prog". substr() slices characters from position 1 to 4 inclusive.

Which function parses 'YYYY-MM-DD' text into a Date?

  • as.Date()
  • strptime.only()
  • date()
  • to.Date()

Answer: as.Date(). as.Date("2024-03-15") returns a proper Date object.

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

  • They are identical
  • sub() replaces the first match; gsub() replaces all
  • gsub() replaces only the first match
  • sub() works only on numbers

Answer: sub() replaces the first match; gsub() replaces all. sub() changes the first match; gsub() ('global') changes every match.

What does d + 30 produce when d is a Date?

  • An error
  • 30 appended as text
  • A Date 30 days later
  • The number 30

Answer: A Date 30 days later. Date arithmetic works in days, so d + 30 is 30 days later.

Which format code gives the four-digit year?

  • "%Y"
  • "%m"
  • "%d"
  • "%B"

Answer: "%Y". format(d, "%Y") returns the four-digit year; %m is month number, %B month name.

What does weekdays(d) return for a Date?

  • The month number
  • The day of the month
  • The name of the weekday
  • The year

Answer: The name of the weekday. weekdays() returns the day-of-week name, e.g. "Friday".

Why convert dates to the Date class instead of leaving them as text?

  • It saves disk space
  • Text looks nicer
  • It changes the time zone
  • Dates support arithmetic, comparison, and chronological sorting

Answer: Dates support arithmetic, comparison, and chronological sorting. Real Dates can be subtracted, compared, and sorted chronologically; text cannot.

Continue this course

Frequently asked questions

How do I join strings together in R?

Use paste() to join strings with a space (by default) or paste0() to join with no separator. For example paste("Hello", name) gives 'Hello Sam', while paste0("file", 1:3) gives 'file1', 'file2', 'file3'. Both are vectorized, so they work element by element across vectors. You can also set a custom separator with paste(..., sep = "-") or collapse a vector into one string with the collapse argument.

What's the difference between sub() and gsub()?

Both find a pattern and replace it, but sub() replaces only the FIRST match in each string, while gsub() ('global sub') replaces ALL matches. So sub("o", "0", "foo") gives 'f0o', but gsub("o", "0", "foo") gives 'f00'. Use gsub() when you want every occurrence changed, which is the more common case for cleaning data. Both accept regular expressions for flexible pattern matching.

How does R store dates, and why use as.Date()?

R has a dedicated Date class that stores a date as the number of days since 1970-01-01. as.Date("2024-03-15") parses a text date into this proper Date type, which then supports arithmetic (d + 30 gives a date 30 days later), comparison, and extraction of parts. Keeping dates as text instead means you can't subtract them or sort them chronologically, so converting to Date early is important for any time-based analysis.

How do I extract the year or month from a date?

Use format() with a format code: format(d, "%Y") for the four-digit year, "%m" for the month number, "%B" for the full month name, "%d" for the day. weekdays(d) gives the day name and months(d) the month name. These return text, so if you need the year as a number wrap it in as.integer(). The lubridate package offers friendlier helpers like year(d) and month(d) if you prefer.