8  Other useful functions

In the previous chapter we saw the main functions to manipulate data and transform a data frame.

Now we’re going to introduce a few more useful functions, with a particular focus on the stringr package.

As usual, let’s start by uploading the needed libraries.

# ETL
library(tidyverse)

Create a demo data frame

Let’s create a demo data frame with 2 variables :

# create vectors
period <- c("10/4/2025", "10/12/2025", "10/17/2025", "10/24/2025", "11/4/2025", "12/5/2025", "12/13/2025", "12/19/2025", "12/26/2025", "1/5/2026", "1/14/2026")

sales <- c(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110)

# combine
df1 <- data.frame(period,
                  sales)

# format the period as a date
df1$period <- as.Date(df1$period, format = "%m/%d/%Y")

# keep results
demo_data <- df1

glimpse(df1)
Rows: 11
Columns: 2
$ period <date> 2025-10-04, 2025-10-12, 2025-10-17, 2025-10-24, 2025-11-04, 20…
$ sales  <dbl> 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110

9 lag() and lead()

Let’s introduce the functions lag() and lead() from the package dplyr.

They are very useful to “navigate” within a data frame and are opposite functions :

  • lag() : will consider the previous rows’ values.

  • lead() : will consider the next rows’ values.

9.1 lag()

In the example below, we will use the function lag() to put on the current row the previous value of the variable “sales”, which is 1, 2 or 3 rows before.

# set a working df
df1 <- demo_data

# create a new variable with lagged sales, which is by default one row
df1 <- df1 |>
  mutate(lagged_sales_1_period = lag(sales))

# we also can lag 2 or 3 rows, for example :
df1 <- df1 |>
  mutate(
    lagged_sales_2_periods = lag(sales, n = 2),
    lagged_sales_3_periods = lag(sales, n = 3)
  )

# display data frame
df1
       period sales lagged_sales_1_period lagged_sales_2_periods
1  2025-10-04    10                    NA                     NA
2  2025-10-12    20                    10                     NA
3  2025-10-17    30                    20                     10
4  2025-10-24    40                    30                     20
5  2025-11-04    50                    40                     30
6  2025-12-05    60                    50                     40
7  2025-12-13    70                    60                     50
8  2025-12-19    80                    70                     60
9  2025-12-26    90                    80                     70
10 2026-01-05   100                    90                     80
11 2026-01-14   110                   100                     90
   lagged_sales_3_periods
1                      NA
2                      NA
3                      NA
4                      10
5                      20
6                      30
7                      40
8                      50
9                      60
10                     70
11                     80

We can see that the variables :

  • lagged_sales_1_period” contains the value of the variable “sales” located 1 row before.

  • lagged_sales_2_periods” contains the value of the variable “sales” located 2 rows before.

  • lagged_sales_3_periods” contains the value of the variable “sales” located 3 rows before.

9.2 lead()

In the following example, we will use the function lead() to put on the current row the next value of the variable “sales”, which is 1, 2 or 3 rows later.

# set a working df
df1 <- demo_data

# create a new variable with lagged sales, which is by default one row
df1 <- df1 |>
  mutate(lead_sales_1_period = lead(sales))

# we also can lead 2 or 3 rows, for example :
df1 <- df1 |>
  mutate(
    lead_sales_2_periods = lead(sales, n = 2),
    lead_sales_3_periods = lead(sales, n = 3)
  )

# display data frame
df1
       period sales lead_sales_1_period lead_sales_2_periods
1  2025-10-04    10                  20                   30
2  2025-10-12    20                  30                   40
3  2025-10-17    30                  40                   50
4  2025-10-24    40                  50                   60
5  2025-11-04    50                  60                   70
6  2025-12-05    60                  70                   80
7  2025-12-13    70                  80                   90
8  2025-12-19    80                  90                  100
9  2025-12-26    90                 100                  110
10 2026-01-05   100                 110                   NA
11 2026-01-14   110                  NA                   NA
   lead_sales_3_periods
1                    40
2                    50
3                    60
4                    70
5                    80
6                    90
7                   100
8                   110
9                    NA
10                   NA
11                   NA

We can see that the variables :

  • lead_sales_1_period” contains the value of the variable “sales” located 1 row later.

  • lead_sales_2_periods” contains the value of the variable “sales” located 2 rows later.

  • lead_sales_3_periods” contains the value of the variable “sales” located 3 rows later.

10 floor_date()

The function floor_date() from the package lubridate allows to quickly transform a date into the beginning of a period it is related to.

For example, the beginning of the week or the beginning of the month.

Let’s illustrate it using the data frame “demo_data” :

# set a working df
df1 <- demo_data

# let's create a week_period variable
# which is the beginning of the week the period is related to
df1$week_period <- floor_date(df1$period, unit = "week")

# let's create a month_year_period variable
# which is the beginning of the month the period is related to
df1$month_year_period <- floor_date(df1$period, unit = "month")

# display data frame
df1
       period sales week_period month_year_period
1  2025-10-04    10  2025-09-28        2025-10-01
2  2025-10-12    20  2025-10-12        2025-10-01
3  2025-10-17    30  2025-10-12        2025-10-01
4  2025-10-24    40  2025-10-19        2025-10-01
5  2025-11-04    50  2025-11-02        2025-11-01
6  2025-12-05    60  2025-11-30        2025-12-01
7  2025-12-13    70  2025-12-07        2025-12-01
8  2025-12-19    80  2025-12-14        2025-12-01
9  2025-12-26    90  2025-12-21        2025-12-01
10 2026-01-05   100  2026-01-04        2026-01-01
11 2026-01-14   110  2026-01-11        2026-01-01

We got 2 new variables :

  • week_period : which is the beginning of the week which contains the value of the variable period.

    • note : by default, the beginning of a week starts on Sunday.
  • month_year_period : which is the beginning of the month which contains the value of the variable period.

11 concatenate

Now, we’re going to look at a way to concatenate values. R offers several options to proceed, and a simple one is to use the function paste().

Let’s first create a new demo data frame with 3 variables :

  • product : 5 items.

  • country : where those products are sold.

  • region : where those countries are located.

# create vectors
product <- c("item1", "item1", "item1", "item2", "item2", "item3", "item3", "item3", "item4", "item4", "item5")

country <- c("Singapore", "Japan", "Taiwan", "Singapore", "Malaysia", "Australia", "Taiwan", "South Korea", "Vietnam", "Thailand", "Philippines")

region <- c("South East Asia", "North Asia", "North Asia", "South East Asia", "South East Asia", "Oceania", "North Asia", "North Asia", "South East Asia", "South East Asia", "South East Asia")

# combine
df1 <- data.frame(product,
                  country,
                  region)

# keep results
demo_data <- df1

# display data frame
demo_data
   product     country          region
1    item1   Singapore South East Asia
2    item1       Japan      North Asia
3    item1      Taiwan      North Asia
4    item2   Singapore South East Asia
5    item2    Malaysia South East Asia
6    item3   Australia         Oceania
7    item3      Taiwan      North Asia
8    item3 South Korea      North Asia
9    item4     Vietnam South East Asia
10   item4    Thailand South East Asia
11   item5 Philippines South East Asia

The paste() function is used to concatenate strings.

We can specify a separator using the sep argument.

Let’s create 2 variables :

  • “DFU” : the concatenation of [product] and [country]. We will separate using the sign “|”.

  • “comment” : a chain of strings with some additional words, to form a short sentence.

# set a working df
df1 <- demo_data

# Concatenate using paste()
df1$DFU <- paste(df1$product, df1$country, sep = "|")

# we also can add some words, for example :
df1$comment <- paste("The", df1$product, "is sold in", df1$country, sep = " ")

# display results
df1
   product     country          region               DFU
1    item1   Singapore South East Asia   item1|Singapore
2    item1       Japan      North Asia       item1|Japan
3    item1      Taiwan      North Asia      item1|Taiwan
4    item2   Singapore South East Asia   item2|Singapore
5    item2    Malaysia South East Asia    item2|Malaysia
6    item3   Australia         Oceania   item3|Australia
7    item3      Taiwan      North Asia      item3|Taiwan
8    item3 South Korea      North Asia item3|South Korea
9    item4     Vietnam South East Asia     item4|Vietnam
10   item4    Thailand South East Asia    item4|Thailand
11   item5 Philippines South East Asia item5|Philippines
                            comment
1    The item1 is sold in Singapore
2        The item1 is sold in Japan
3       The item1 is sold in Taiwan
4    The item2 is sold in Singapore
5     The item2 is sold in Malaysia
6    The item3 is sold in Australia
7       The item3 is sold in Taiwan
8  The item3 is sold in South Korea
9      The item4 is sold in Vietnam
10    The item4 is sold in Thailand
11 The item5 is sold in Philippines

12 separate

We also can split a concatenated variable, using the function separate() .

Let’s keep only 2 variables from the previous example :

df1 <- df1 |> select(region, DFU)

Now let’s separate the variable DFU, using the sign “|” as separator.

# separate variable
df_separated <- df1 |>
  separate(DFU, into = c("product", "country"), sep = "\\|")

# display
df_separated
            region product     country
1  South East Asia   item1   Singapore
2       North Asia   item1       Japan
3       North Asia   item1      Taiwan
4  South East Asia   item2   Singapore
5  South East Asia   item2    Malaysia
6          Oceania   item3   Australia
7       North Asia   item3      Taiwan
8       North Asia   item3 South Korea
9  South East Asia   item4     Vietnam
10 South East Asia   item4    Thailand
11 South East Asia   item5 Philippines

In this particular example, we need to write a double backlash “\\” before the sign “|”.

It’s because in R, the pipe character (|) is interpreted as a special character in regular expressions. Regular expressions are used for pattern matching and text manipulation, and certain characters have special meanings within them.

13 round

There are a few ways to round numbers.

Here are the most common ways : round up, round down, and at a specific number of digits after the comma.

13.1 round up

We use the function ceiling().

# Round up the value 3.728
rounded_value <- ceiling(3.728)

# display value
rounded_value
[1] 4

13.2 round down

We use the function floor() .

# Round down the value 3.728
rounded_value <- floor(3.728)

# display value
rounded_value
[1] 3

13.3 at 1 digit

We use the function round(), and specify after the comma the number of digits we want .

# Round the value 3.728 to one decimal place
rounded_value <- round(3.728, 1)

rounded_value
[1] 3.7

14 more about stringr

14.1 Pad a string

This is useful when you want to add a white space to a string to make sure it has a certain length.

Using the function str_pad(), it’s possible to add a white space on the left side, right side, or on both sides. Let’s look at the example below :

# set a working df
df1 <- demo_data

# add pad
df1 <- df1 |> 
  mutate(
    country_both = str_pad(country, width = 20, side = "both"),
    country_left = str_pad(country, width = 20, side = "left"),
    country_right = str_pad(country, width = 20, side = "right")
  )

# display data frame
df1
   product     country          region         country_both
1    item1   Singapore South East Asia      Singapore      
2    item1       Japan      North Asia        Japan        
3    item1      Taiwan      North Asia        Taiwan       
4    item2   Singapore South East Asia      Singapore      
5    item2    Malaysia South East Asia       Malaysia      
6    item3   Australia         Oceania      Australia      
7    item3      Taiwan      North Asia        Taiwan       
8    item3 South Korea      North Asia     South Korea     
9    item4     Vietnam South East Asia       Vietnam       
10   item4    Thailand South East Asia       Thailand      
11   item5 Philippines South East Asia     Philippines     
           country_left        country_right
1             Singapore Singapore           
2                 Japan Japan               
3                Taiwan Taiwan              
4             Singapore Singapore           
5              Malaysia Malaysia            
6             Australia Australia           
7                Taiwan Taiwan              
8           South Korea South Korea         
9               Vietnam Vietnam             
10             Thailand Thailand            
11          Philippines Philippines         

14.2 Collapse a vector of strings

You want to collapse a vector of strings into a single string.

A classic use case is when you want to write your R object as a csv or an excel file, as the list format needs to be converted into a simple character string.

First, let’s create a list of countries where our products are sold.

# set a working df
df1 <- demo_data

# create a list
df1 <- df1 |> group_by(product) |>
      summarise(country = list(country)) 

# display data frame
df1
# A tibble: 5 × 2
  product country  
  <chr>   <list>   
1 item1   <chr [3]>
2 item2   <chr [2]>
3 item3   <chr [3]>
4 item4   <chr [2]>
5 item5   <chr [1]>

Now, let’s collapse this list, using the function below, through sapply().

Note : we will see in the next chapters how to create a function.

The variable “country” is now a character, capturing all the values which were inside the vector, and separating them with a “;” symbol.

# Convert list column to a character string
df1 <- df1 |> mutate(country = sapply(country, 
                                      function(x) paste(x, collapse = "; "))
                     )

df1
# A tibble: 5 × 2
  product country                       
  <chr>   <chr>                         
1 item1   Singapore; Japan; Taiwan      
2 item2   Singapore; Malaysia           
3 item3   Australia; Taiwan; South Korea
4 item4   Vietnam; Thailand             
5 item5   Philippines                   

14.3 Detect matches in a string

14.3.1 inside a character

You want to check if a regular expression matches in a string. We can use the function str_detect().

In the example below, we want to identify the rows for which the variable “country” has strings which contain the pattern “an”.

We’re going to create a new variable called “contains_an” to identify those rows, based on the function str_detect() .

# set a working df
df1 <- demo_data

# create a new variable 'contains_an' using str_detect
df1$contains_an <- str_detect(df1$country, "an")

# display data frame
df1
   product     country          region contains_an
1    item1   Singapore South East Asia       FALSE
2    item1       Japan      North Asia        TRUE
3    item1      Taiwan      North Asia        TRUE
4    item2   Singapore South East Asia       FALSE
5    item2    Malaysia South East Asia       FALSE
6    item3   Australia         Oceania       FALSE
7    item3      Taiwan      North Asia        TRUE
8    item3 South Korea      North Asia       FALSE
9    item4     Vietnam South East Asia       FALSE
10   item4    Thailand South East Asia        TRUE
11   item5 Philippines South East Asia       FALSE

14.3.2 inside a vector

It also works when we apply it to a list of values.

Let’s create a new variable called “list_of_country” which displays, as a list (i.e. here a vector) the list of the countries where the product X is sold.

This list of country will be presented as c("Singapore", "Japan", "Taiwan") for example.

# set a working df
df1 <- demo_data

# create a list
df1 <- df1 |> group_by(product) |>
      summarise(list_of_country = list(country)) 

# Create a new variable 'contains_Singapore' using str_detect
df1$contains_Singapore <- str_detect(df1$list_of_country, "Singapore")
Warning in stri_detect_regex(string, pattern, negate = negate, opts_regex =
opts(pattern)): argument is not an atomic vector; coercing
# display data frame
df1
# A tibble: 5 × 3
  product list_of_country contains_Singapore
  <chr>   <list>          <lgl>             
1 item1   <chr [3]>       TRUE              
2 item2   <chr [2]>       TRUE              
3 item3   <chr [3]>       FALSE             
4 item4   <chr [2]>       FALSE             
5 item5   <chr [1]>       FALSE             

Looking at the variable “contains_Singapore” in this table, we can quickly identify the rows, items, which are concerned.

14.4 Match the start or end of a string

When you want to write a regular expression that matches strings that start or end with a particular pattern.

We can use the functions str_starts() and str_ends().

Note : they are “case sensitive”, which means that they will consider the capital or small characters.

# set a working df
df1 <- demo_data

# ending with "an"
df1$ends_with_an <- str_ends(df1$country, "an")

# starting with "Vi"
df1$starts_with_vi <- str_starts(df1$country, "Vi")

# display data frame
df1
   product     country          region ends_with_an starts_with_vi
1    item1   Singapore South East Asia        FALSE          FALSE
2    item1       Japan      North Asia         TRUE          FALSE
3    item1      Taiwan      North Asia         TRUE          FALSE
4    item2   Singapore South East Asia        FALSE          FALSE
5    item2    Malaysia South East Asia        FALSE          FALSE
6    item3   Australia         Oceania        FALSE          FALSE
7    item3      Taiwan      North Asia         TRUE          FALSE
8    item3 South Korea      North Asia        FALSE          FALSE
9    item4     Vietnam South East Asia        FALSE           TRUE
10   item4    Thailand South East Asia        FALSE          FALSE
11   item5 Philippines South East Asia        FALSE          FALSE

14.5 Filter based on a string

We previously see that we can identify the strings which contain, starts or ends with a particular pattern.

Now, we’re going to see how we can filter the rows related to those patterns. For this, we just need to combine 2 functions : the function filter() together with str_starts() or str_ends() or str_detect() .

14.5.1 starts with

Let’s filter the rows of the data frame demo_data, for which the variable country starts with the pattern “Ph”.

# set a working df
df1 <- demo_data

# filter
df1 <- df1 |> filter(str_starts(country, "Ph"))

# display data frame
df1
  product     country          region
1   item5 Philippines South East Asia

14.5.2 ends with

Let’s filter the rows of the data frame demo_data, for which the variable country ends with the pattern “an”.

# set a working df
df1 <- demo_data

# filter
df1 <- df1 |> filter(str_ends(country, "an"))

# display data frame
df1
  product country     region
1   item1   Japan North Asia
2   item1  Taiwan North Asia
3   item3  Taiwan North Asia

14.5.3 contains

Let’s filter the rows of the data frame demo_data, for which the variable country contents the pattern “ai”.

# set a working df
df1 <- demo_data

# filter
df1 <- df1 |> filter(str_detect(country, "ai"))

# display data frame
df1
  product  country          region
1   item1   Taiwan      North Asia
2   item3   Taiwan      North Asia
3   item4 Thailand South East Asia

14.6 Count the number of matches of a pattern in a string

Let’s continue on our dataset demo_data.

Let’s say that we want to know in how many countries of the region “North Asia” each product is sold.

We can :

  • create a list with all the regions where a product is sold, based on the location of the country.

  • then use the function str_count() to “screen” the list, and count the occurrences of the pattern we’re looking for.

# set a working df
df1 <- demo_data

# create a list
df1 <- df1 |> group_by(product) |>
      summarise(region = list(region))

# count the number of occurrences of the value "North Asia" within the variable "region"
df1 <- df1 |>
  mutate(
    counts_nb_occurences = str_count(region, pattern = "North Asia")
  )

# display data frame
df1
# A tibble: 5 × 3
  product region    counts_nb_occurences
  <chr>   <list>                   <int>
1 item1   <chr [3]>                    2
2 item2   <chr [2]>                    0
3 item3   <chr [3]>                    2
4 item4   <chr [2]>                    0
5 item5   <chr [1]>                    0