Skip to content

Instantly share code, notes, and snippets.

@batpigandme
Last active August 27, 2017 12:57
Show Gist options
  • Select an option

  • Save batpigandme/e72b507fc30519188baed442141d589b to your computer and use it in GitHub Desktop.

Select an option

Save batpigandme/e72b507fc30519188baed442141d589b to your computer and use it in GitHub Desktop.
Tidy evaluation, most common actions by Edwin Thoen Source: https://edwinth.github.io/blog/dplyr-recipes/
---
title: "Tidy evaluation, most common actions"
author: "Edwin Thoen"
date: "2017-08-25"
output:
html_document:
keep_md: TRUE
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.path = 'fig/', dev = 'png', dpi = 100, fig.retina = 2)
```
Source: <https://edwinth.github.io/blog/dplyr-recipes/>
Tidy evaluation is a bit challenging to get your head around. Even after reading programming with dplyr several times, I still struggle when creating functions from time to time. I made a small summary of the most common actions I perform, so I don’t have to dig in the vignettes and on stackoverflow over and over. Each is accompanied with a minimal example on how to implement it. I thought others might find this useful too, so here it is in a blog post. This list is meant to be a living thing so additions and improvements are most welcome. Please do a PR on this file or send an email.
```{r libs, message=FALSE, warning=FALSE}
library(tidyverse)
```
## bare to quosure: **quo**
```{r bare_quo_fun}
bare_to_quo <- function(x, var){
x %>% select(!!var) %>% head(1)
}
```
```{r bare_quo_ex}
bare_to_quo(mtcars, quo(cyl))
```
## bare to quosure in function: **enquo**
```{r enquo_fun}
bare_to_quo_in_func <- function(x, var) {
var_enq <- enquo(var)
x %>% select(!!var_enq) %>% head(1)
}
```
```{r enquo_ex}
bare_to_quo_in_func(mtcars, mpg)
```
## quosure to a name: **quo_name**
```{r quo_name_fun}
bare_to_name <- function(x, nm) {
nm_name <- quo_name(nm)
x %>% mutate(!!nm_name := 42) %>% head(1) %>%
select(!!nm)
}
```
```{r quo_name_ex}
bare_to_name(mtcars, quo(this_is_42))
```
## quosure to text: **quo_text**
```{r quo_text_fun}
quo_to_text <- function(x, var) {
var_enq <- enquo(var)
ggplot(x, aes_string(rlang::quo_text(var_enq))) + geom_density()
}
```
```{r quo_text_ex}
plt <- quo_to_text(mtcars, cyl)
```
Note that tidy evaluation is not yet implemented in `ggplot2`, but this will be in future versions. This is a workaround for the meantime, when combining `dplyr` and `ggplot2`.
## character to quosure: **sym** (edited)
```{r sym_fun}
char_to_quo <- function(x, var) {
var_enq <- rlang::sym(var)
x %>% select(!!var_enq) %>% head(1)
}
```
```{r sym_ex}
char_to_quo(mtcars, "vs")
```
## multiple bares to quosure: **quos**
```{r quos_fun}
bare_to_quo_mult <- function(x, ...) {
grouping <- quos(...)
x %>% group_by(!!!grouping) %>% summarise(nr = n())
}
```
```{r quos_ex}
bare_to_quo_mult(mtcars, vs, cyl)
```
## multiple characters to quosure: **syms** (edited)
```{r syms_fun}
bare_to_quo_mult_chars <- function(x, ...) {
grouping <- rlang::syms(...)
x %>% group_by(!!!grouping) %>% summarise(nr = n())
}
```
```{r syms_ex}
bare_to_quo_mult_chars(mtcars, list("vs", "cyl"))
```
## quoting full expressions
Although quoting column names is most often used, it is by no means the only option. We can use the above to quote full expressions.
```{r exps_fun}
filter_func <- function(x, filter_exp) {
filter_exp_enq <- enquo(filter_exp)
x %>% filter(!!filter_exp_enq)
}
```
```{r exps_ex}
filter_func(mtcars, hp == 93)
```
### Edit notes
I mistakenly thought that `rlang::sym(s)` created quosures. However, as pointed out to me by a reader, this creates a `name`, not a `quosure`. A `name` however can also be unquoted.
```{r just_a_name}
just_a_name <- rlang::sym("cyl")
class(just_a_name)
```
```{r name_ex}
mtcars %>% select(!!just_a_name) %>% head(1)
```

Tidy evaluation, most common actions

Edwin Thoen
2017-08-25

Source: https://edwinth.github.io/blog/dplyr-recipes/

Tidy evaluation is a bit challenging to get your head around. Even after reading programming with dplyr several times, I still struggle when creating functions from time to time. I made a small summary of the most common actions I perform, so I don’t have to dig in the vignettes and on stackoverflow over and over. Each is accompanied with a minimal example on how to implement it. I thought others might find this useful too, so here it is in a blog post. This list is meant to be a living thing so additions and improvements are most welcome. Please do a PR on this file or send an email.

library(tidyverse)

bare to quosure: quo

bare_to_quo <- function(x, var){
  x %>% select(!!var) %>% head(1)
}
bare_to_quo(mtcars, quo(cyl))
##           cyl
## Mazda RX4   6

bare to quosure in function: enquo

bare_to_quo_in_func <- function(x, var) {
  var_enq <- enquo(var)
  x %>% select(!!var_enq) %>% head(1)
}
bare_to_quo_in_func(mtcars, mpg)
##           mpg
## Mazda RX4  21

quosure to a name: quo_name

bare_to_name <- function(x, nm) {
  nm_name <- quo_name(nm)
  x %>% mutate(!!nm_name := 42) %>% head(1) %>% 
    select(!!nm)
}
bare_to_name(mtcars, quo(this_is_42))
##   this_is_42
## 1         42

quosure to text: quo_text

quo_to_text <- function(x, var) {
  var_enq <- enquo(var)
  ggplot(x, aes_string(rlang::quo_text(var_enq))) + geom_density()
}
plt <- quo_to_text(mtcars, cyl)

Note that tidy evaluation is not yet implemented in ggplot2, but this will be in future versions. This is a workaround for the meantime, when combining dplyr and ggplot2.

character to quosure: sym (edited)

char_to_quo <- function(x, var) {
  var_enq <- rlang::sym(var)
  x %>% select(!!var_enq) %>% head(1)
}
char_to_quo(mtcars, "vs")
##           vs
## Mazda RX4  0

multiple bares to quosure: quos

bare_to_quo_mult <- function(x, ...) {
  grouping <- quos(...)
  x %>% group_by(!!!grouping) %>% summarise(nr = n())
}
bare_to_quo_mult(mtcars, vs, cyl)
## # A tibble: 5 x 3
## # Groups:   vs [?]
##      vs   cyl    nr
##   <dbl> <dbl> <int>
## 1     0     4     1
## 2     0     6     3
## 3     0     8    14
## 4     1     4    10
## 5     1     6     4

multiple characters to quosure: syms (edited)

bare_to_quo_mult_chars <- function(x, ...) {
  grouping <- rlang::syms(...)
  x %>% group_by(!!!grouping) %>% summarise(nr = n())
}
bare_to_quo_mult_chars(mtcars, list("vs", "cyl"))
## # A tibble: 5 x 3
## # Groups:   vs [?]
##      vs   cyl    nr
##   <dbl> <dbl> <int>
## 1     0     4     1
## 2     0     6     3
## 3     0     8    14
## 4     1     4    10
## 5     1     6     4

quoting full expressions

Although quoting column names is most often used, it is by no means the only option. We can use the above to quote full expressions.

filter_func <- function(x, filter_exp) {
  filter_exp_enq <- enquo(filter_exp)
  x %>% filter(!!filter_exp_enq)
}
filter_func(mtcars, hp == 93)
##    mpg cyl disp hp drat   wt  qsec vs am gear carb
## 1 22.8   4  108 93 3.85 2.32 18.61  1  1    4    1

Edit notes

I mistakenly thought that rlang::sym(s) created quosures. However, as pointed out to me by a reader, this creates a name, not a quosure. A name however can also be unquoted.

just_a_name <- rlang::sym("cyl")
class(just_a_name)
## [1] "name"
mtcars %>% select(!!just_a_name) %>% head(1)
##           cyl
## Mazda RX4   6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment