Jim
Jim

Reputation: 172

Source R file in reactive context (Shiny)

Beginner Shiny question.

I have two models living in different folders, A and B, both called inputs.R, and want to load one or the other using selectInput to choose the folder (in reality, there is more than one file in each folder, so I don't want to load the file directly).

Currently, I have

ui <- fluidPage(selectInput("model_folder", "Select folder", c("A", "B")))

server <- function(input, output){
    reactive({
    inpts <- paste0("models/",input$model_folder, "/inputs.R") 
    source(inpts, local = T)
    })
}

This does not work. Any thoughts would be greatly appreciated.

Upvotes: 2

Views: 1192

Answers (1)

Rorschach
Rorschach

Reputation: 32426

This will depend where you have your 'models' folder stored. So, pretend it is in the same directory as your shiny app. Here is some code that should recreate this situation, along with some models and data in the two separate folders. Just change the variable appDir to wherever you don't have a folder.

## Create the models/folders in a temporary location
## define it in appDir
appDir <- 'c:/path/to/temp/app'
dir.create(appDir)
dir.create(file.path(appDir, "models"))
for (i in 1:2) {
    dir.create((folder = file.path(appDir, "models/", LETTERS[i])))
    code <- bquote({
        dat <- data.frame((x=rnorm(100)), y=rnorm(100, mean=.(i)*x))
        mod <- lm(y ~ x, data=dat)
    })
    writeLines(deparse(code), file.path(folder, 'input.R'))
}

Then, in the new folder appDir, create a file app.R, which will be the example application. There are problems with how you are trying to use reactive, illustrated below. I capture all the variables from the sourced input.R files using mget() in this example.

library(shiny)

app <- shinyApp(
    ui = fluidPage(
        selectInput("model_folder", "Select folder", c("A", "B")),
        uiOutput('info'),
        tableOutput('summ')
    ),
    server = function(input, output) {
        output$info <- renderUI({
            inp <- inpts()
            list(
                helpText(sprintf("Now looking at variables from %s", inp$name)),
                radioButtons('vars', 'Variables', choices=names(inp), inline=TRUE)
            )
        })

        output$summ <- renderTable({
            inp <- inpts()
            if (input$vars == 'mod') summary(inp$mod)
        })

        inpts <- reactive({
            name <- file.path("models", input$model_folder, "input.R")
            source(name, local=TRUE)
            mget(ls())
        })
    }
)

Now, to run it you can just do

library(shiny)
runApp(appDir = normalizePath(appDir))

Upvotes: 1

Related Questions