1

I am trying to build a tool where the user can select a number of parameters (e.g partner, budget, month, year) and get back a foretasted value for next months metric.

I have built several external functions to perform the task. Each function performs some tasks and passes the data onto the next function and the final function builds four models, forecasts using those models, builds the ggplots and stores them in a list which one can access once the functions are run.

How do I extract the plots and forecasts to be shown through a Shiny App?

UI:

ui <- fluidPage(
  titlePanel("Forecasting Tool"),

  sidebarLayout(
    sidebarPanel(

  selectInput("Partner", h3("Partner"), 
      choices = list("all", "dsp","search","social"), selected = "all"),

       numericInput("Budget", 
           h3("Budget"), 
           value = 10000),

  selectInput("Month", h3("Month"), 
              choices = list("January", "February", "March", "April","May", 
                        "June", "July", "August", "September", "October", 
                        "November", "December"), 
            selected = "January"),

  selectInput("Year", h3("Year"), 
              choices = list(2018,2019), 
              selected = 2019),


   submitButton("Submit"), h3("")),

mainPanel(plotOutput("plot"))

  )
)

How do I build my server function such that it recognizes that the submit button has been triggered and runs the external functions?

my final function is called reg_mod and it triggers all the other functions, and then returns the final objects in a list (plots, forecasts, etc) the input it takes is as follows:

reg_mod(partner, budget, month, year)

Can I access the objects and output them in the server function based on user input? for instance:

plot = reg_mod(input$Partner, input$Budget, input$Month, input$year)

output$plot = renderPlot(plot[[1]])

where plot[[1]] calls the first object which is a plot from reg_mod

EDIT:

So here is an example of a helper function which creates some data and outputs a plot which I want to source into a shiny App, similar to what I want to do. (note, the only month selection option is "August" and year 2017 which is fine, can just run the app and run the default).

Helper = function(partner, budget, month, year){

 nums = seq(0 , 10, length.out = 100)

 Registrations = 5 + 2*rnorm(100, 20, 7)*nums
 dates = seq.Date(as.Date("2017-01-01"), as.Date("2017-04-10"), by ="days")

  Registrations = data.frame(Date = dates, Registrations = Registrations)

  if(partner == "dsp" & month == "August" & year == 2017){

    Registrations$Registrations = 0.5*budget*Registrations$Registrations
  }

  if(partner == "search" & month == "August" & year == 2017){

    Registrations$Registrations = 2*budget*Registrations$Registrations

  }

  if(partner == "social" & month == "August" & year == 2017){

    Registrations$Registrations = budget*Registrations$Registrations

  }

  Plot = ggplot(data = Registrations, aes(x = Date)) + 
    geom_line(aes(y = Registrations, colour = "Actual"), size = 1)

  List_Read = list("Plot" = Plot)

  return(List_Read)

}

and here are my UI and Server functions:

library(shiny)
library(ggplot2)
# Define UI for application that outputs ggplot
ui <-  fluidPage(
  titlePanel("Forecasting Tool"),

  sidebarLayout(
    sidebarPanel(

     selectInput("Partner", h3("Partner"), 
            choices = list("all", "dsp","search","social"), selected="dsp"),

  numericInput("Budget", 
               h3("Budget"), 
               value = 100),

selectInput("Month", h3("Month"), 
              choices = list("January", "February", "March", "April","May", 
              "June", "July",  "August", "September", "October", "November", 
              "December"), 
              selected = "August"),

  selectInput("Year", h3("Year"), 
              choices = list(2017,2018), 
              selected = 2017),


       submitButton("Submit"), h3("")),

mainPanel(plotOutput("plot"))

 )
)
# Define server logic required to output ggplot from helper function
server <- function(input, output, session) {

  source("C:/Users/ksiopes/Documents/Ad Hoc/Survival/Prefinal Insights 
   Function Files/For Shiny Function/Testing/Helper3.R", 
     local = FALSE)

  plot_List = eventReactive(input$Submit,{

    Helper(input$Partner, input$Budget, input$Month, input$Year)

  })

  #Output the plot
  output$plot<- renderPlot({
    plot = plot_List()
    plot[[1]]
  })

}

# Run the application 
shinyApp(ui = ui, server = server)

Edit 2:

library(shiny)
library(ggplot2)


source("C:/Users/ksiopes/Documents/Ad Hoc/Survival/Prefinal Insights 
Function Files/For Shiny Function/Testing/Helper3.R", local = TRUE)

# Define UI for application that uses function to create random data and 
output ggplot
ui <-  fluidPage(
  titlePanel("Forecasting Tool"),

  sidebarLayout(
    sidebarPanel(

      selectInput("Partner", h3("Partner"), 
              choices = list("all", "dsp","search","social"), selected = 
"dsp"),

      numericInput("Budget", 
                   h3("Budget"), 
                   value = 100),

      selectInput("Month", h3("Month"), 
                  choices = list("January", "February", "March", 
                   "April","May", "June", "July", "August", "September", 
                    "October", "November", "December"), 
              selected = "August"),

      selectInput("Year", h3("Year"), 
                  choices = list(2017,2018), 
                  selected = 2017),


      submitButton("Submit"), h3("")),

    mainPanel(plotOutput("plot"))

  )
)

# Define server logic required to run sourced function and output ggplot
server <- function(input, output, session) {


  plot_List = eventReactive(input$Submit,{



    Helper(input$Partner, input$Budget, input$Month, input$Year)


  })
    #Output the plot
    output$plot<- renderPlot({
    plot = plot_List()
    plot[[1]]

    })



}

# Run the application 
shinyApp(ui = ui, server = server)
Keith
  • 103
  • 1
  • 9
  • Your question might be too broad for us to help with effectively here. I'd strongly recommend starting with a simple `shiny` tutorial to get comfortable with the way you connect `ui` and `server` functions – divibisan Jan 14 '19 at 16:54

1 Answers1

2

Here is a general framework on how to go about this:

Loading in external functions to a shiny app requires a little extra work as opposed to a local script, but not much. We can still use the source function, the only difference is local=T must be set, and the function must be placed in the app directory. One the function is sourced, we can pass user inputs to it relatively easily.

Step 1) Save script with function in app directory (where server.R & ui.R or app.R is)

Step 2) Source the function

#Basically source the path to the function file you put in the app directory
source("your-app-dir/functions.R")

Step 3) Use the function, output the plot

server.R

server<-function(input,output,session){

#Function reg_mod in this file
source("your-app-dir/functions.R")

#Assuming the return of reg_mod is correct
plot_List<-eventReactive(input$Submit, {

reg_mod(input$Partner, input$Budget, input$Month, input$year)

})

#Output the plot
output$plot<- renderPlot({
plot<-plot_List()
plot[[1]] 
})


}

Additional help about using external functions in Shiny can be found here

Additional help regarding use of reactive environments in this example here

Edit: The fix to the graph not rendering is you are not activating your function to run since you are using an incorrect ui element. It should be actionButton not submitButton

actionButton("Submit", "Submit"), Use this instead

Full Code

library(shiny)
library(ggplot2)


source("Helper3.R", local = TRUE)

# Define UI for application that uses function to create random data and 

ui <-  fluidPage(
  titlePanel("Forecasting Tool"),

  sidebarLayout(
    sidebarPanel(

      selectInput("Partner", h3("Partner"), 
                  choices = list("all", "dsp","search","social"), selected = 
                    "dsp"),

      numericInput("Budget", 
                   h3("Budget"), 
                   value = 100),

      selectInput("Month", h3("Month"), 
                  choices = list("January", "February", "March", 
                                 "April","May", "June", "July", "August", "September", 
                                 "October", "November", "December"), 
                  selected = "August"),

      selectInput("Year", h3("Year"), 
                  choices = list(2017,2018), 
                  selected = 2017),


      actionButton("Submit", "Submit"), 

      h3("")),

    mainPanel(plotOutput("plot"))

  )
)

# Define server logic required to run sourced function and output ggplot
server <- function(input, output, session) {


  plot_List<-eventReactive(input$Submit, {

    print("ran")
    Helper(input$Partner, input$Budget, input$Month, input$Year)



  })
  #Output the plot
  output$plot<- renderPlot({
    plot = plot_List()
    plot[[1]]

  })



}

# Run the application 
shinyApp(ui = ui, server = server)
Chabo
  • 2,842
  • 3
  • 17
  • 32
  • Thank you so much! I will try it out. – Keith Jan 14 '19 at 17:07
  • One other question: should I wrap the eventReactive function in observeEvent, input$Submit, {....}? thanks – Keith Jan 14 '19 at 17:08
  • @Keith The `eventReactive` is an `observeEvent` in of itself, the only difference is this will return a variable (we would use one or the other, not both). We are watching for an event, `eventReactive(input$Submit, ...` so on submit being pressed that code block will run, and return a value for the reactive variable `plot_List` – Chabo Jan 14 '19 at 17:10
  • and here is an explanation of that principal https://stackoverflow.com/questions/33519816/shiny-what-is-the-difference-between-observeevent-and-eventreactive – Chabo Jan 14 '19 at 17:11
  • thank you so much for your help. It is so incredibly appreciated. You went above and beyond to answer my question. I am having a hard time still getting the plot to output in the main panel of the app. I'm not sure what could be happening,. I have been toying around with the code but can't seem to get the thing to output. Any thoughts on troubleshooting? Thanks! – Keith Jan 18 '19 at 15:12
  • @Keith I would work my way backwards, start by ensuring that `plot_List()` is created (do this by using `print(plot_List())`) under the `renderPlot`. If this exists, check the class of the object and ensure it is a compatible type for renderPlot, as well as ensuring your ui object label you are outputting to matches the server and ui. If `plot_List()` does not exist work your way backwards to find what went into making it, in your case `reg_mod`, make sure this function is returning properly. – Chabo Jan 18 '19 at 15:35
  • hey man, thanks so much for your reply!!!! So I edited my question and built a random helper function which creates some data and spits out a ggplot. I also created my UI and Server functions which I want to use to show that outputed plot in the main panel. This is pretty much what I am going for, but even when I run it like this, I do not see the output. The helper function by itself runs fine and I can extract the plot, but inside the app, it does not output for me. I tried printing under renderplot, getting rid of renderplot and printing and still nothing. let me now if you can guide – Keith Jan 21 '19 at 23:50
  • @Keith Try setting `local=T` in the source call – Chabo Jan 22 '19 at 15:18
  • Also your file path may be a problem. Put the Helper3.R script in the same folder where your shiny app is, and then you can use `source("Helper3.R", local = TRUE)`. Also you should use the source function at the beginning with the library calls – Chabo Jan 22 '19 at 15:29
  • Thanks again man for following up with me. I have tried the above fixes i.e. saved the helper3 function to the folder where app.r is, put the source function under the library calls, and set the local = TRUE, but couldn't get the output :/ – Keith Jan 22 '19 at 20:02
  • @Keith please update your question with your current test code being used. – Chabo Jan 22 '19 at 20:35
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187143/discussion-between-chabo-and-keith). – Chabo Jan 22 '19 at 20:48
  • any luck with getting the output? – Keith Jan 23 '19 at 18:03