rfunctionggplot2nsedirect-labels

R / nse / Double-handover of a variable to a sub-function


I have two functions I want to wrap together in a wrapping function for usability. The wrapping function includes a variable (a column name within a dataframe) which should be handed over from the wrapping function to one of the subfunctions.

Strongly reduced example:

Subfunction 1: Create data

datafun <- function() {

    df_data <- data.frame(x = rep(1:20, 3), 
                          y = rnorm(60),
                          ga = sample(c("a", "b"), 30, replace = TRUE),
                          gb = sample(c("x", "y"), 20, replace = TRUE))

    df_data
}

Subfunction 2: Plotting

plotfun <- function(df, gvar) {

    gvar_q = deparse(substitute(gvar))

    g <- ggplot2::ggplot(df, ggplot2::aes_string(x = "x", y = "y", color = gvar_q)) +
        ggplot2::geom_line() +
        directlabels::geom_dl(ggplot2::aes(label = {{gvar}}), method = list("last.points"))

    g
}

Wrapping function

wrapfun <- function(gvar) {

    dat <- datafun()
    plot <- plotfun(df = dat, gvar = {{gvar}})

    plot
}

Testing

Using the two subfunctions directly works without a problem:

#works
d <- datafun()
plotfun(d, gvar = ga)

Using the wrapping function however leads to an error

# doesn't work
wrapfun(gvar = ga)
>Error in FUN(X[[i]], ...) : object 'ga' not found

Note that (as far as I have understood), directlabels::geom_dl does not accept aes_string as workaround. So it seems I can't hand over gvar as a string to the function.


Solution

  • In latest versions of ggplot, you don't use deparse/substitute or aes_string. You use the new quasinotation syntax exclusively. With this example you should do just

    plotfun <- function(df, gvar) {
    
       ggplot2::ggplot(df, ggplot2::aes(x = x, y = y, color = {{gvar}})) +
         ggplot2::geom_line() +
         directlabels::geom_dl(ggplot2::aes(label = {{gvar}}), method = list("last.points"))
    
    }
    

    Then your function will work both directly and within wrapfun()