Unlocking Tidyeval: Writing Flexible and Reusable R Code with Quo Objects and dplyr

Introduction to tidyeval: Programming with tidyr and dplyr

tidyverse is a collection of R packages that provide a comprehensive set of tools for data manipulation, analysis, and visualization. Two of the most popular packages in the tidyverse family are tidyr and dplyr. In this article, we will delve into the world of tidyeval, a new feature introduced in the latest versions of tidyr and dplyr that enhances the functionality of these packages.

What is tidyeval?

tidyeval is a set of tools for working with R code as strings, rather than just executing them. This approach allows us to write more flexible, reusable, and maintainable code. The tidyeval package provides several key features, including:

  • Quo objects: These are the core building blocks of tidyeval. They represent a specific piece of code, such as a variable or function name.
  • Enquo objects: These are used to create new quo objects from existing ones. For example, we can use enquo() to convert a simple R expression into an enquo object.
  • Quo expressions: These are full-fledged R expressions that include quo objects.

The mutate_all() function

The mutate_all() function in the dplyr package is a powerful tool for applying a set of operations to every column of a data frame. In this article, we will explore how to use tidyeval with mutate_all() to create more flexible and reusable code.

Case Study: Using tidyeval with unite()

Let’s consider a classic example from the problem statement itself - using unite(). We want to combine two columns into one column named “hello”. The original code is:

mtcars %>% 
  as_tibble() %>% 
  select(mpg , cyl) %>% 
  mutate_all(as.character) %>% 
  unite(col = hello, sep = "/") %>% 
  mutate(hello = str_replace(hello, "/", ""))

However, we can improve this code using tidyeval:

unite_fun <- function(df, var1 = mpg, var2 = cyl, col_name = hello){
  var1 <- enquo(var1)
  var2 <- enquo(var2)
  col_name <- enquo(col_name)

  mtcars %>% 
    as_tibble() %>% 
    select(!!var1 , !!var2) %>% 
    mutate_all(as.character) %>% 
    unite(col = !!col_name, sep = "/") %>% 
    mutate(!!quo_name(col_name) := str_replace(!!quo_name(col_name), "/", ""))
}

unite_fun(mtcars, mpg, cyl)

Here’s a breakdown of the changes:

  • We define a new function unite_fun() that takes three arguments: df, var1, and var2. The col_name argument has a default value of “hello”.
  • Inside the function, we create enquo objects for var1 and var2 using enquo().
  • We also create an enquo object for col_name using enquo(), just like var1 and var2.
  • However, when it comes to mutate(), we need to use quo expressions. This is where quo_name() comes in handy.
  • Inside the mutate() function, we use !!quo_name(col_name) to refer to the col_name enquo object, and !!col_name for the original string value.

Using Quo objects

Quo objects are a powerful tool for creating more flexible and reusable code. They allow us to work with R expressions as strings, rather than just executing them.

Let’s explore how we can use quo objects to further improve our code:

unite_fun <- function(df, var1 = mpg, var2 = cyl, col_name = hello){
  var1 <- enquo(var1)
  var2 <- enquo(var2)
  col_name <- enquo(col_name)

  mtcars %>% 
    as_tibble() %>% 
    select(!!var1 , !!var2) %>% 
    mutate_all(as.character) %>% 
    unite(col = quo(col_name), sep = "/") %>% 
    mutate(quo(col_name):= str_replace(quo(col_name), "/", ""))
}

unite_fun(mtcars, mpg, cyl)

Here’s a breakdown of the changes:

  • Instead of using !!col_name directly in the mutate() function, we use quo(col_name).
  • When calling unite(), we pass a new quo object created with quo().
  • Inside the mutate() function, we use quo(col_name) to refer to the original string value.

Conclusion

In this article, we’ve explored how to use tidyeval with the unite() and mutate_all() functions in the tidyverse. By working with R expressions as strings using quo objects, we can create more flexible, reusable, and maintainable code.

Key Takeaways

  • Quo objects are a key part of tidyeval.
  • Enquo objects allow us to create new quo objects from existing ones.
  • Quo expressions represent full-fledged R expressions that include quo objects.
  • We can use enquo() and quo() functions to work with R expressions as strings.

Further Reading

For more information on tidyeval, we recommend checking out the following resources:


Last modified on 2024-06-18