call R script from Shiny App

14,776

Scoping in Shiny

All this largely depends on where exactly you call source(). If you need the data to be found from within both the UI and the server function, you put source() outside the app.

If you place source() inside the server function, the UI won't be able to find any object created by the script. If you put this inside a render function, the objects are only visible inside that render function. See also Scoping rules for Shiny

Note that if you have separate server.R and ui.R files and you want the UI to find the objects created by the script, you should add a global.R file to your app directory. The source() command then goes in the global.R file.

A small example:

source('testScript.R')

shinyApp(
  fluidPage(
    selectInput("cols", "pick columns",
                 choices = names(x)),
    dataTableOutput("what")),
  function(input, output, session){
    output$what <- renderDataTable(x)
  }
)

and testScript.R contains one line:

x <- iris

The key here is:

  1. the script actually has to create these objects
  2. the script should be sourced in the correct spot.

So if you can do the following:

shinyApp(
  fluidPage(
    selectInput("cols", "pick columns",
                 choices = names(x)),
    dataTableOutput("what")),
  function(input, output, session){
    source('testScript.R', local = TRUE)
    output$what <- renderDataTable(x)
  }
)

you get an error about not being able to find x. That's normal, because x is now only defined inside the environment of the server function.

You still can do this though:

shinyApp(
  fluidPage(
    dataTableOutput("what")),
  function(input, output, session){
    source('R/testScript.R', local = TRUE)
    output$what <- renderDataTable(x)
  }
)

Note how x is only needed inside the server function, not inside the UI.

Using functions

For functions, the same thing applies. You put the function definition in a script and source it like before. A function is nothing else but an object, so the script essentially creates a function object that then can be found using the exact same scoping rules.

Keep in mind though that this function should return something if you want to use the result of the function. So put this trivial example in testScript.R:

myfun <- function(x){
  tmp <- iris[x]
  return(tmp)
}

And now you can do the following:

source('testScript.R', local = TRUE)

shinyApp(
  fluidPage(
    selectInput("cols", "pick columns",
                choices = names(myfun())),
    dataTableOutput("what")),
  function(input, output, session){
    output$what <- renderDataTable(myfun(input$cols))
  }
)

This doesn't work any longer if you put the source() inside the server function. The UI side won't be able to see myfun() any more.

rm(list = ls())
shinyApp(
  fluidPage(
    selectInput("cols", "pick columns",
                choices = names(myfun())),
    dataTableOutput("what")),
  function(input, output, session){
    source('R/testScript.R', local = TRUE)
    output$what <- renderDataTable(myfun(input$cols))
  }
)
# Error in myfun() : could not find function "myfun"
Share:
14,776
Luis Cano
Author by

Luis Cano

Updated on August 07, 2022

Comments

  • Luis Cano
    Luis Cano over 1 year

    I developed a shiny app which displays some dynamic charts. These charts are generated at execution time according to the value of some buttons. This shiny app gets the data from a raw csv which is previously treated and transformed. I got a Rscript apart from the shiny app to do all those "transformations" of the raw data. What I would like to do is to call this Rscript from the shiny app in order to be executed when the shiny app is launched.

    I have already checked these links but it didn't help at all: How can I connect R Script with Shiny app in R? and this one using Source() in Shiny. I checked the Rstudio documentation too: http://shiny.rstudio.com/tutorial/lesson5/.

    I think it should be something like this, being procesadoDatos.R the RScript. i just want the source command to be executed at the beginning in order to load the data as the shiny app is starting:

     source("procesadoDatos.R",local = TRUE)
     shinyServer(function(input, output,session) {
     (renderplots, reactives elements and so on)}
    

    The Rscript is the shiny project path as the server.R and UI.R files. I also tried including the path but it didn't work either.

    Another thing I tried was to create a function which makes all the transformations and then call it from server.R file after sourcing it:

     source("procesadoDatos.R",local = TRUE) 
     generate_data(ticketsByService_report10.csv)
    

    Being generate_data this function defined in the RScript:

     generate_data <- function(csv_file) {
     (all those transformation, data frame an so on)}
    

    In all cases I got the same error saying that the data frames which are generated in the RScript aren't found.

    Does anyone know what is wrong? Thanks in adavance