Search code examples
rggplot2shinyr-highcharter

Pass a parameter to reactive function


My problem is as follows, and I suspect it has a simple solution. However I looked at create reactive function from user input and Reactive Function Parameter, neither of which answer my question.

I have a chart which will have X and Y axes that may change based on user input. The user will be able to click on the chart, and I have a text display which says something along the lines of 'You have selected a (name of x label) value of xxx, and a (name of y label) value of yyy'. Obviously, if the name of the x or y label begins with a vowel, I would like to use 'an' rather than 'a'. For the moment I have written this function twice into the server module, but this isn't very elegant.

Is there a way to define a function inside the server function which I can just send the label name to, and which will simply return 'a' or 'an'? Code below. Note the Pokemon dataset travels with the highcharter package and can be downloaded from CRAN.

library(ggplot2)
library(highcharter)

myData <- pokemon

ui <- fluidPage(
  # Some custom CSS for a smaller font for preformatted text
  tags$head(
    tags$style(HTML("
                    pre, table.table {
                    font-size: smaller;
                    }
                    "))
    ),
  tags$head(tags$style(type = "text/css", ".shiny-text-output, .well{background-color: #EFF8CD;}")),

  fluidRow(
    column(width = 3
           ),
    column(width = 5,
           plotOutput("plot1", height = 450,
                      # Equivalent to: click = clickOpts(id = "plot_click")
                      click = "plot_click"
           )
    ),
    column(width = 4,
           ## Text output here.
             wellPanel(
               h4("Your results"),
               htmlOutput("chartDetails")
             )
           )
  )
)


server <- function(input, output) {
  output$plot1 <- renderPlot({
      ggplot(myData, aes(weight, attack)) + geom_point()
    }
  )

  ## Extract some values when plot is clicked
  inputX <- reactive({
    if (is.null(input$plot_click$x))
        {
          -999
          }
    else
      {
        round(input$plot_click$x, 0)
      }
    })
  inputY <- reactive({
    if (is.null(input$plot_click$y))
    {
    -999
    }
    else
    {
     round(input$plot_click$y, 0) 
    }
  })

  labelX <- eventReactive(input$plot_click, {
    input$plot_click$mapping$x
  })
  labelY <- eventReactive(input$plot_click,{
    input$plot_click$mapping$y
  })

  ## count the number of points that have a higher x and y.
  mySubset <- eventReactive(input$plot_click, {
    #myFirstSubset <- subset(myData, weight > inputX())
    subset(myData, labelX() > inputX() & labelY() > inputY())
    })


  ## Create relevant strings out of the inputX and inputY values.
  stringX <- reactive({
    if (inputX() > -999)
    {
      myString <- "You have selected"
      if (substr(labelX(), 1,1) %in% c("a", "e", "i", "o", "u"))
      {
        myString <- paste(myString, "an")
      }
      else
      {
        myString <- paste(myString, "a")
      }
      paste(myString, labelX(), "of", inputX())
    }
    else
    {
      ""
    }
  })

  stringY <- reactive({
    if (inputY() > -999)
    {
      myString <- "and"
      if (substr(labelY(), 1,1) %in% c("a", "e", "i", "o", "u"))
      {
        myString <- paste(myString, "an")
      }
      else
      {
        myString <- paste(myString, "a")
      }
      paste(myString, labelY(), "of", inputY())
    }
    else
    {
      ""
    }
  })

  stringCount <- reactive({
    if (inputY() > -999 && inputX() > -999)
    {
      paste("The number of records with higher",labelX(), "and", labelY(), "is", nrow(mySubset()))
    }
    else
    {
      ""
    }
  })

  ## Post the results to the chart details well.
  output$chartDetails <- renderUI({
    if (inputX() > -999 && inputY() > -999) {

    HTML(paste(stringX(), "<br>",
               stringY(), "<br>",
               stringCount()))
    }
    else
    {
      HTML("Click on the chart")
    }

  })

}

    shinyApp(ui, server)

Solution

  • I do not know exactly if this is what you want, but you can substitute the two functions for the vowel function

    vowel <- function(myString, label){
        if (substr(label, 1,1) %in% c("a", "e", "i", "o", "u"))
       {
         myString <- paste(myString, "an")
       }
       else
       {
         myString <- paste(myString, "a")
       }
       return(myString)
     }
    
     ## Create relevant strings out of the inputX and inputY values.
     stringX <- reactive({
       if (inputX() > -999)
       {
         myString <- "You have selected"
    
         paste(vowel(myString,labelX()), labelX(), "of", inputX())
       }
       else
       {
         ""
       }
     })
    
     stringY <- reactive({
       if (inputY() > -999)
       {
         myString <- "and"
    
         paste(vowel(myString,labelY()), labelY(), "of", inputY())
       }
       else
       {
         ""
       }
     })