Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functions and non-standard evaluation in dplyr

Tags:

function

r

dplyr

I just finished reading 'Programming with dplyr' and 'Define aesthetic mappings programatically' to start to get a grip on non-standard evaluation of functions. The specific question for this post is, "How do I write the code directly below using the tidyverse (eg quo(), !!, etc.)" instead of the base-R approach eval(), substitute, etc..

library(tidyverse)
xy <- data.frame(xvar = 1:10, yvar = 11:20)

plotfunc <- function(data, x, y){
  y.sqr <- (eval(substitute(y), envir = data))^2
  print(
    ggplot(data, aes_q(x = substitute(x), y = substitute(y.sqr))) + 
      geom_line()
  )
}

plotfunc(xy, xvar, yvar)

Can you provide the answer? It would be a bonus if you could work in the following concept, being, why is the function above non-standard whereas this other function below is standard? I read the Advanced R chapters on functions and non-standard evaluation, but it's above my head at this point. Can you explain in layperson terms? The function below is clear and concise (to me) whereas the function above is a hazy mess.

rescale01 <- function(x) {
  rng <- range(x, na.rm = TRUE)
  (x - rng[1]) / (rng[2] - rng[1])
}
rescale01(c(0, 5, 10))
like image 700
stackinator Avatar asked Oct 18 '18 14:10

stackinator


Video Answer


2 Answers

You could do the following :

library(tidyverse)
xy <- data.frame(xvar = 1:10, yvar = 11:20)

plotfunc <- function(data, x, y){
  x <- enquo(x)
  y <- enquo(y)
  print(
    ggplot(data, aes(x = !!x, y = (!!y)^2)) + 
      geom_line()
  )
}
plotfunc(xy, xvar, yvar)

Non standard evaluation basically means that you're passing the argument as an expression rather than a value. quo and enquo also associate an evaluation environment to this expression.

Hadley Wickham introduces it like this in his book :

In most programming languages, you can only access the values of a function’s arguments. In R, you can also access the code used to compute them. This makes it possible to evaluate code in non-standard ways: to use what is known as non-standard evaluation, or NSE for short. NSE is particularly useful for functions when doing interactive data analysis because it can dramatically reduce the amount of typing.

like image 127
Moody_Mudskipper Avatar answered Oct 17 '22 21:10

Moody_Mudskipper


With rlang_0.4.0, we can use the tidy-evaluation operator ({{...}}) or curly-curly which abstracts quote-and-unquote into a single interpolation step. This makes it easier to create functions

library(rlang)
library(ggplot2)
plotfunc <- function(data, x, y){

  print(
    ggplot(data, aes(x = {{x}}, y = {{y}}^2)) + 
      geom_line()
  )
}
plotfunc(xy, xvar, yvar)

-output

enter image description here

like image 4
akrun Avatar answered Oct 17 '22 22:10

akrun