Search code examples
rrlangquosure

Using quosure inside ggplot function annotate


I have produced the below scatter plot function.

scatter_fun<-function(data,xval,yval,xlabel,ylabel, labels){
  xval <- enquo(xval)
  yval <- enquo(yval)
  
  ggplot(data, aes(!!xval, !!yval))+
    geom_smooth(method=lm, se=FALSE)+
    geom_point()+
    theme(axis.line.x.bottom = element_line("black"),
          axis.line.y.left = element_line("black"),
          axis.text.x = element_blank(),
          legend.title = element_blank())+ylab(ylabel)+
    xlab(xlabel)+
    scale_y_continuous(labels = scales::comma)+
    expand_limits(y = 0)+
    geom_smooth(method="lm", se=FALSE, colour="red")+
    annotate("text",
             x=max(!!xval)/2,
             y =0,
             label = labels)
  }

I however cannot get the annotate part of the equation to work. If I call the function, I get the error:

Error: Quosures can only be unquoted within a quasiquotation context.

Bad:

list(!!myquosure)

Good:

dplyr::mutate(data, !!myquosure)

However, when I remove the annotate part of the code, it works just fine. What do I have to change in the code to get it to work?


Solution

  • If you capture the symbols with ensym, you can eval them in the context of df:

    scatter_fun<-function(data,xval,yval,xlabel,ylabel, labels){
      xval <- ensym(xval)
      yval <- ensym(yval)
      
      ggplot(data, aes(!!xval, !!yval))+
        geom_smooth(method=lm, se=FALSE)+
        geom_point()+
        theme(axis.line.x.bottom = element_line("black"),
              axis.line.y.left = element_line("black"),
              axis.text.x = element_blank(),
              legend.title = element_blank())+ylab(ylabel)+
        xlab(xlabel)+
        scale_y_continuous(labels = scales::comma)+
        expand_limits(y = 0)+
        geom_smooth(method="lm", se=FALSE, colour="red")+
        annotate("text",
                 x=max(eval(xval, data))/2,
                 y =0,
                 label = labels)
    }
    
    df <- data.frame(x = rnorm(100), y = rnorm(100))
    
    scatter_fun(df, x, y, "x", "y", "my labels")
    

    enter image description here