2
votes

I'm using R shiny in combination with ggplot to visualize a certain dataset. I want the user to be able to add values to this dataset. I can get my application so far as to show me the original data + one data point, but as soon as the user enters a new point, the old one is gone: the user-input data is not actually stored in my dataframe.

Some of the code I'm using (changed variable names for simplicity):

shinyServer(
  function(input, output) {     
    output$newPlot <- renderPlot({   
      input$addButton
      isolate({
        x <- as.numeric(input$x)
        y <- as.numeric(input$y)
        if (!is.na(y)) {
          data <- rbind(data, data.frame(x = x, y = y))

          # more code here

        }

        # more code here 

        plot <- myPlot(data)
        print(plot)

      })
    })
  }
)

The user can give values for x and y with textInput and then submit those values with a button (actionButton). Each time the user hits 'add', the most recently inputted values for x and y are shown on top of the original data, but any other values the user inputted (in the same session) are lost. How do I get shiny to remember my users inputs and plot all of it?

1
Do you want the new inputs permanently stored (i.e. still there if you restart the shiny app?) or just for the session?cdeterman
Just for the session.Marleen

1 Answers

4
votes

I cannot reproduce yours specifically given the code you provided but perhaps an example will help you. The part you need is reactiveValues, this allows you to store your dataset and update it throughout the session as you see fit. Perhaps this can help you fix your problem?

require(shiny)
data(iris)

runApp(
  list(
    ui = fluidPage(
      headerPanel('Adding Data'),
      sidebarPanel(
        textInput("species", label="Add a new species", value="Enter species"),
        numericInput("sepal.length", label="Add a new sepal length", value=""),
        numericInput("sepal.width", label="Add a new speal width", value=""),
        numericInput("petal.length", label="Add a new petal length", value=""),
        numericInput("petal.width", label="Add a new petal width", value=""),
        actionButton("addButton", "UPLOAD!")
      ),
      mainPanel(
        tableOutput("table"))
    ),

    server = function(input, output) {     
      # just a small part of iris for display
      iris_sample <- iris[sample(nrow(iris), 10),]
      row.names(iris_sample) <- NULL

      # The important part of reactiveValues()
      values <- reactiveValues()
      values$df <- iris_sample
      observe({

        # your action button condition
        if(input$addButton > 0) {
          # create the new line to be added from your inputs
          newLine <- isolate(c(input$sepal.length, input$sepal.width, input$petal.length, input$petal.width, input$species))
          # update your data
          # note the unlist of newLine, this prevents a bothersome warning message that the rbind will return regarding rownames because of using isolate.
          isolate(values$df <- rbind(as.matrix(values$df), unlist(newLine)))
        }
      })
      output$table <- renderTable({values$df}, include.rownames=F)
    }
  )
)