How to update models within shiny if new data is provided?

Hello,

I want to create a shiny page with a model (already exists). Yet, additional to the "old" models implemented I would like the user to be able to upload new data and combine it with the old data. Based on this new data I want to create a new model and display, this discarding the old model. If the user does not upload new data I want the old model and data to be displayed. In short if(new){new model + new plot}else{old model + old plot}. However, the (example) code below only displays the plot if new data is provided, but not the old model if no data is provided. I am not able to figure out how to incorporate this into the reactive environment. Does anyone know how to incorporate this in shiny?

Thank you in advance,

library(shiny)

#stored in app folder as model1
x <- 1:100
set.seed(123)
y1<- 1.5*x+rnorm(100,0,50)
old <- data.frame(x,y1)
model1 <- lm(y1~.,data = old)

#Uploaded as new data
#set.seed(1)
#y2 <- 1.43*x+rnorm(100,0,40)
#new <- data.frame(x,y2)
#write.csv(new,file = "new.csv",row.names = F)

#shiny app
ui <- fluidPage(

    titlePanel("Stuff"),

    sidebarPanel(fileInput("file1", "Upload file y~x.",
                           multiple = FALSE,
                           accept = c("text/csv",
                                      "text/comma-separated-values,text/plain",
                                      ".csv"))),

        mainPanel(
           plotOutput("Plot")
        )
    )

server <- function(input, output, session) {
    
    newdata <- reactive({
    
         req(input$file1)
        
         new <- input$file1
        
         if(is.null(new)){return(old)}else{

         new <- as.data.frame(read.csv(input$file1$datapath, stringsAsFactors = TRUE))
    
         colnames(new)<-c("x","y1")
         
         return(rbind(old, new))}})
    

    output$Plot <- renderPlot({
        
        new <- newdata()
        
        if(!is.null(new)){
        
        plot(new)
        abline(lm(new$y1~.,data=new))}else{
            plot(old)
            abline(model1)}
})
    
}

shinyApp(ui = ui, server = server)

the file input aspect seems a distraction from the main question of how to approach this, so I removed it from the reprex.

library(shiny)
library(tidyverse)

#stored in app folder as model1
x <- 1:100
set.seed(123)
y1<- 1.5*x+rnorm(100,0,50)
old <- data.frame(x,y1)
model1 <- lm(y1~.,data = old)

#Uploaded as new data
set.seed(1)
y2 <- 1.43*x+rnorm(100,0,40)
new <- data.frame(x,y2)
#write.csv(new,file = "new.csv",row.names = F)

#shiny app
ui <- fluidPage(
   
   titlePanel("Stuff"),
   
   sidebarPanel(checkboxInput("newloadtgl",label="simulate new file loaded")),
   
   mainPanel(
      plotOutput("Plot")
   )
)

server <- function(input, output, session) {
   
   newdata <- reactiveVal(NULL)
   
   observeEvent(input$newloadtgl,
                {
                   if(input$newloadtgl){
                      newdata({
                         rbind(old,new %>% setNames(c("x","y1")))
                      })
                   } else
                      newdata(NULL)
                })

   
   
   output$Plot <- renderPlot({
      
      new1 <- newdata()
      
      if(!is.null(new1)){
         
         plot(new1)
         abline(lm(y1~.,data=new1))}else{
            plot(old)
            abline(model1)}
   })
   
}

shinyApp(ui = ui, server = server)
1 Like

[quote="nirgrahamuk, post:2, topic:105869"]

I seem to get the following error. Also, if no file is provided it will return an error since there is no new data to bind? Or, am I wrong?

Warning: Error in <-: names() applied to a non-vector
  84: setNames
  83: function_list[[k]]
  81: freduce
  80: _fseq
  79: eval
  78: eval
  76: %>%
  72: observeEventHandler [C:...app.R#40]
   1: runApp

Minor edit, it works if reactiveVal() and observeEvent()
are replaced by

    newdata <- reactive({
        inFile <- input$file1
        if (is.null(inFile)){return(NULL)}else{
        new <- as.data.frame(read.csv(input$file1$datapath, stringsAsFactors = TRUE))
        colnames(new) <- c("x","y1")
        return(rbind(old, new))}
    })

The app directly creates the new model over the old then, the issue is you cannot go back to the old model, unless you refresh the page.

not when you run the code I supplied as I supplied it, surely ? :thinking:

You are right, not if I run the code provided. But your example gave me some difficulties incorporating it in the code, although it gave me information to look for some other solutions +1. Coding jargon is often a difficult topic searching for solution without a coding background.

I can recommend https://mastering-shiny.org/ as a great reference

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.