简体   繁体   中英

Load and save shiny inputs

I have a big shiny app with about 60 different inputs and it's still growing. Since I use this program a lot, I wanted the settings to be stored until next time I run the app. I made a csv-file that looks something like this:

input,value
input_a,10
input_b,#FFF000
input_c,hide
input_d,65400

I load the csv-file in ui.R and server.R with (not sure why I have to load it two times...)

config <- data.frame(lapply(read.csv(".//config.csv"), as.character), stringsAsFactors = FALSE)

and have inputs like this

sliderInput(
"input_a",
"Number of cats:",
min = 1,max = 50,
value = config[config$input %in% "input_a", "value"]
)

In server.R, I let input changes replace the value in the table and also save the table to the file

observe({
config[config$input %in% "input_a", "value"] <- input$input_a
config[config$input %in% "input_b", "value"] <- input$input_b
config[config$input %in% "input_c", "value"] <- input$input_c
config[config$input %in% "input_d", "value"] <- input$input_d

write.table(config, file = ".//config.csv", col.names = TRUE, row.names = FALSE, quote = FALSE, sep = ",")
})

I'm sure there is a better way to do this, I searched and checked the other similar questions, I started with dget and dput, but then decided to have all relevant settings in one simple file. Sorry if I missed the most relevant question when I searched.

What I don't like about this is that the program also saves the table when it loads the program, before I make any input changes.

How can I get rid of that unnecessary save every time I run the program? I don't understand all the "reactivity" in shiny, it's still a bit to complicated for me, I don't really know anything about R or programming, just trying to optimize my program since it gets slower with every new "feature" I add.

I don't see any problem with keeping settings like that, but there might be a better way, and in anycase I would wrap it in a function like I did here.

And here is how you implement writing only "on exit" though (also please note the session parameter which is often not used):

library(shiny)
settingsdf <- data.frame(input=c("input_a","input_b","input_c"),
                         value=c(10,"#FF000","hide"),
                         stringsAsFactors=F)
setSetting <- function(pname,pval){
  idx <- which(settingsdf$input==pname)
  if (length(idx)==1){
    print(pval)
    settingsdf[ idx,2] <<- pval
  }
}
shinyApp(
  ui = fluidPage(
    selectInput("region", "Region:", choices = colnames(WorldPhones)),
    plotOutput("phonePlot")
  ),
  server = function(input, output, session) {


    output$phonePlot <- renderPlot({
      if (length(input$region)>0){
        setSetting("input_a",input$region)
        barplot(WorldPhones[,input$region]*1000, 
                ylab = "Number of Telephones", xlab = "Year")
      }
    })
    session$onSessionEnded(function() {
      write.csv(settingsdf,"settings.csv")
    })
  },
  options = list(height = 500)
)

Note that I am compressing the ui.R and server.R files into a single file which is not normally done but is nicer for these little examples.

This is not perfect code, I don't read the settings in and initialize the variables, and I use the <<- operator, which some people frown on. But it should help you along.

Update

Here is a more complex version that loads and saves the parameters, and encapsulates them for use. It is better, although it probably should use S3 objects...

library(shiny)

# Settings code

settingsdf <- data.frame(input=c("input_a","region"),
                        value=c(10,"Asia"),stringsAsFactors=F)
setfname <- "settings.csv"

setSetting <- function(pname,pval){
  idx <- which(settingsdf$input==pname)
  if (length(idx)==1){
    settingsdf[ idx,"value"] <<- pval
  }
}
getSetting <- function(pname){
  idx <- which(settingsdf$input==pname)
  if (length(idx)==1){
    rv <- settingsdf[ idx,"value"]
    return(rv)
  } else {
    return("")
  }
}
readSettings <- function(){
  if (file.exists(setfname)){
    settingsdf <<- read.csv(setfname,stringsAsFactors=F)
  }
}
writeSettings <- function(){
  write.csv(settingsdf,setfname,row.names=F)
}

# ShinyApp

shinyApp(
  ui = fluidPage(
    selectInput("region","Region:", choices = colnames(WorldPhones)),
    plotOutput("phonePlot")
  ),
  server = function(input, output, session) {
    readSettings()
    vlastinput <- getSetting("region")
    if (vlastinput!=""){
        updateSelectInput(session, "region", selected = vlastinput )
    }
    output$phonePlot <- renderPlot({
      if (length(input$region)>0){
        vlastinput <- input$region
        setSetting("region",vlastinput)
        barplot(WorldPhones[,input$region]*1000, 
                ylab = "Number of Telephones", xlab = "Year")
      }
    })
    session$onSessionEnded(function() {
      writeSettings()
    })
  },
  options = list(height = 500)
)

Yielding:

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM