Open In App

Quosures in R language

Last Updated : 21 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

While coding in R programming language, we often need to store certain expressions which later need to be evaluated in a particular environment according to the requirements of the problem. This can be seen as a delayed evaluation of an expression, which is the major reason for using quosures.

Now before learning more about this concept, to give you an overview of what actually quosures are, you can compare it with ‘macro‘ in C programming.

What are Quosures?

Quosure is a special type of object in R that can be used for delayed evaluation of expressions. The expression can be any mathematical function, variable, function call, or collection of data frames. It is created by the enquo() or enquos() functions. They play an important role in the tidy evaluation framework as they avoid repetitive writing of the same expression for multiple uses in the program.

Various functions and their uses:

1. quo() – The function simply returns its input expression along with the captured environment in which it is called. The expression is not evaluated when it is captured, so the quosure can be passed as an argument to another function that can then evaluate the expression in a different context.

R




library(rlang)
quo_expr <- quo(a * b)
a<-10
b<-20
quo_expr


Output:         

The code displays only the expression and environment but does not evaluate the product as ‘a’ and ‘b’ variables.

<quosure>
expr: ^a * b
env:  global

2. enquo() It is used a bit differently from quo() which takes in an expression as an argument and can evaluate in the context of a given dataset. It is used in functions that use Non-standard evaluation (NSE) to capture arguments as quosures, so that the arguments can be evaluated in any particular context.

R




library(dplyr) 
new_function <- function(data, var) {
  var_quosure <- enquo(var)
  data %>%
    select(!!var_quosure)
}
  
x<-c(10,20,30)
y<-c(5,10,15)
z<-c(1,2,3)
data<-data.frame(x,y,z)
  
print(new_function(data,x))


Output:

The ‘!!’ (bang-bang) operator evaluates the expression captured within the ‘var_ quosure’. The same implementation could also be obtained without using the enquo() by using “x” as a character variable and passing it to the new_function(). The use of character variables in complex expressions can make it difficult to handle and debug the code.

   x
1 10
2 20
3 30

R




new_function <- function(data, var_name) {
    select(data,var_name)
}
x <- c(10,20,30)
y <- c(5,10,15)
z <- c(1,2,3)
data <- data.frame(x,y,z)
print(new_function(data,"x"))


This code will produce the same output as the previous code’s output.

3. enquos()The enquos() function in R is used to capture multiple unevaluated arguments as a list of quosure objects. From the above example, if we need to display x, y, and z variables at the same time, we pass them together as a list of arguments in enquos() function.

R




new_function <- function(data,...) {
  var_quosure <- enquos(...)
  select(data,!!!var_quosure)
}
  
x<-c(10,20,30)
y<-c(5,10,15)
z<-c(1,2,3)
data<-data.frame(x,y,z)
print(new_function(data,x,y,z))


Output:

   x  y z
1 10  5 1
2 20 10 2
3 30 15 3

Why use enquo() instead of expr()?

A brief overview of expr() is that it is very much similar in use to enquo() and defuses(returns its content as it is) an expression instead of evaluating it which can later be used. But the confusion arises as to when to use the enquo() instead of expr() as both are responsible for capturing or manipulating expressions in R, depending on the context.

The expr() is basically used to create an expression object from a character string or a symbolic representation and does not support multiple expressions as list objects as in enquos() feature. It is neither used in functions to capture variables as arguments nor display its values based on the data frame. Logically, it is just a copy-paste feature for various expressions but quosure objects is a far more flexible tool to implement delayed evaluation of code.

Summary

In R programming language, quosures are useful tools to improve the flexibility and reusability of our code. It gives the overall program a tidy look as the repeating elements of the solution can be avoided by capturing them within a quosure. Quosures are evaluated only when they are called and not during their declaration. Let us think of a case when we need the value of an expression later in our code but we do not want to evaluate it earlier as it can alter the execution of our program, we can capture the expression and the environment within a quosure and evaluate it later on.

It is a bit tricky to understand the complete use and concept of quosure. They are used in various fields of R such as Data Masking, and Abstract Syntax Trees which we will be understanding in detail in our future articles.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads