Search code examples
rggplot2shinyggplotly

How to specify an arbitrary amount of variables in aes in a generic function in R?


I am making a shiny application where the user specifies the independent variables and as a result shiny displays a time series plot with plotly, where on-however each point shows the selected parameters.

enter image description here enter image description here

If I know the exact number of variables that the user selects, I am able to construct the time series plot without a problem. Let's say there are 3 parameters chosen:

ggp <- ggplot(data = data.depend(), aes(x = Datum, y = y, tmp1 = .data[[input$Coockpit.Dependencies.Undependables[1]]], tmp2 = .data[[input$Coockpit.Dependencies.Undependables[2]]], tmp3 = .data[[input$Coockpit.Dependencies.Undependables[3]]])) + 
     geom_point()
ggplotly(ggp)

where data.depend() looks like enter image description here

and the selected parameters are stored in a character vector enter image description here

So the problem is that for each parameter I want to include in the tooltip, I have to hard code it in the aes function as tmpi = .data[[input$Coockpit.Dependencies.Undependables[i]]]. I would however like to write generic function that handles any amount of selected parameters. Any comment suggestions are welcome.

EDIT: Below a minimal working example:

data.dummy <- data.frame(Charge = c(1,2,3,4,5), Datum = c(as.Date("2020-01-01"),as.Date("2020-01-02"),as.Date("2020-01-03"),as.Date("2020-01-04"),as.Date("2020-01-05")), y = c(4,5,6,4,5), ZuluftTemperatur = c(52,51,54,58,49), Durchflussgeschwindigkeit = c(690, 716,722,710,801), ZuluftFeuchtigkeit= c(3.9,4.1,3.8,3.0,4.9))
ChosenParams <- c("ZuluftTemperatur", "ZuluftFeuchtigkeit", "Durchflussgeschwindigkeit")
ggp <- ggplot(data = data.dummy, aes(x = Datum, y = y,  tmp1 = .data[[ChosenParams[1]]], tmp2 = .data[[ChosenParams[2]]], tmp3 = .data[[ChosenParams[3]]])) + geom_point()
ggplotly(ggp)

Result:

enter image description here

So this works at the "cost" of me knowing the user is choosing three parameters and therefore I write in aes tmpi = .data[[ChosenParams[i]]]; i=1:3. I am interested in a solution with the same result but where I don't have to write tmpi = .data[[ChosenParams[i]]] i-number of times

Thank you!


Solution

  • One solution is to use eval(parse(...)) to create the code for you:

    library(ggplot2)
    library(plotly)
    
    data.dummy <- data.frame(Charge = c(1,2,3,4,5), Datum = c(as.Date("2020-01-01"),as.Date("2020-01-02"),as.Date("2020-01-03"),as.Date("2020-01-04"),as.Date("2020-01-05")), y = c(4,5,6,4,5), ZuluftTemperatur = c(52,51,54,58,49), Durchflussgeschwindigkeit = c(690, 716,722,710,801), ZuluftFeuchtigkeit= c(3.9,4.1,3.8,3.0,4.9))
    ChosenParams <- c("ZuluftTemperatur", "ZuluftFeuchtigkeit", "Durchflussgeschwindigkeit")
    
    ggp <- eval(parse(text = paste0("ggplot(data = data.dummy, aes(x = Datum, y = y, ",
                                    paste0("tmp", seq_along(ChosenParams), " = .data[[ChosenParams[", seq_along(ChosenParams), "]]]", collapse = ", "),
                                    ")) + geom_point()"
                                    )
                      ))
    
                
    ggplotly(ggp)
    

    Just note that this is not very efficient and in some cases it is not advised to use it (see What specifically are the dangers of eval(parse(...))?). There might also be a way to use quasiquotation in aes(), but I am not really familiar with it.

    EDIT: Added a way to do it with quasiquotation.

    I had a look a closer look at quasiquotations in aes() and found a nicer way to do it using syms() and !!!:

    data.dummy <- data.frame(Charge = c(1,2,3,4,5), Datum = c(as.Date("2020-01-01"),as.Date("2020-01-02"),as.Date("2020-01-03"),as.Date("2020-01-04"),as.Date("2020-01-05")), y = c(4,5,6,4,5), ZuluftTemperatur = c(52,51,54,58,49), Durchflussgeschwindigkeit = c(690, 716,722,710,801), ZuluftFeuchtigkeit= c(3.9,4.1,3.8,3.0,4.9))
    ChosenParams <- c("ZuluftTemperatur", "ZuluftFeuchtigkeit", "Durchflussgeschwindigkeit")
    names(ChosenParams) <- paste0("tmp", seq_along(ChosenParams))
    ChosenParams <- syms(ChosenParams)
    
    ggp <- ggplot(data = data.dummy, aes(x = Datum, y = y, !!!ChosenParams)) + geom_point()
    ggplotly(ggp)