Search code examples
rhighchartsr-highcharter

Use highcharter inside a function


How do I use highcharter::hchart inside a function?

Here is a simple line graph using the hchart function.

library(tidyverse)
library(lubridate)
library(highcharter)
library(nycflights13)

flights_2 <- flights %>% 
  mutate(dep_mo = ymd(str_c(year, month, "01", sep = "-"))) %>% 
  group_by(dep_mo) %>% 
  summarize(arr_delay = mean(arr_delay, na.rm = TRUE))

hchart(flights_2, 
       type = "line", 
       hcaes(x = dep_mo, y = arr_delay), 
       name = "Average Arrival Delay")

When I try to write a function to create the same graph I get an error.

h_fun <- function(df, x, y) {
  hchart(df, 
         type = "line",
         hcaes(x = x, y = y),
         name = "Average Arrival Delay"
         )
 }

 h_fun(df = flights_2, x = dep_mo, y = arr_delay)

This is the error message: Error in mutate_impl(.data, dots) : Binding not found: x.

When I traceback the error it seems hchart is using dplyr::mutate_. This leads me to believe the error has something to do with NSE and maybe hchart needs something akin to ggplot2::aes_string() (link). However, I can't find any documentation on a similar function in highcharter.

enter image description here


Solution

  • We need to use enquo() & quo_name() together with hcaes_string

    • enquo() captures the expression supplied as argument by the user & returns a quosure.
    • quo_name() squashes the quosure and transforms it into a string.

    Watch Hadley explained tidyeval in this 5min video if you haven't heard about it. More on tidyeval here

    library(tidyverse)
    library(lubridate)
    library(highcharter)
    library(nycflights13)
    
    flights_2 <- flights %>% 
      mutate(dep_mo = ymd(str_c(year, month, "01", sep = "-"))) %>% 
      group_by(dep_mo) %>% 
      summarize(arr_delay = mean(arr_delay, na.rm = TRUE))
    
    h_fun2 <- function(df, x, y) {
      x <- enquo(x)
      y <- enquo(y)
      hchart(df, 
             type = "line",
             hcaes_string(quo_name(x), quo_name(y)),
             name = "Average Arrival Delay"
      )
    }
    
    h_fun2(df = flights_2, x = dep_mo, y = arr_delay)
    

    enter image description here

    Edit: as of April 18, 2018, the development version of highcharter supports tidyeval so h_fun2 can be rewritten as:

    h_fun2 <- function(df, x, y) {
      x <- enexpr(x)
      y <- enexpr(y)
      hchart(df, 
             type = "line",
             hcaes(!!x, !!y),
             name = "Average Arrival Delay"
      )
    }