Ju Ko
Ju Ko

Reputation: 508

R Shiny: Switching datasets based on user input

I am working on a shiny app where users can upload their own data and get some plots and statistics back. However, I also want to include an example dataset that gets used instead if the user presses a specific button. Importantly, the plots should be reactive so that users get updated plots whenever they click on the "use example data instead" button or upload a new file. I tried to recreate my current approach of overwriting the data object as best as I could here, but simply defining the data object twice doesn't overwrite the data in the way I hoped it would. Any suggestions are appreciated.

library(shiny)

# UI
ui <- fluidPage(

    # Application title
    titlePanel("Reproducible Example"),

    # Sidebar with a slider input for number of bins 
    sidebarLayout(
        sidebarPanel(

            fileInput("Upload", "Upload your own Data"),

            actionButton("Example", "Use Example Data instead")

        ),

        # Show a plot of the generated distribution
        mainPanel(

            plotOutput("hist")

        )
    )
)

# Server Logic
server <- function(input, output) {

        data <- eventReactive(input$Upload,{input$Upload})
        data <- eventReactive(input$Example, {faithful$eruptions})

        output$hist <- renderPlot({hist(data())})

}

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 1

Views: 2504

Answers (2)

Andrew Feierman
Andrew Feierman

Reputation: 128

You can use a reactive value to access whether the user has chosen to use an example dataset or use their own dataset. The user can choose to switch between the active dataset using an input from your UI.

Here's the official explanation on reactive values from RStudio: link

This would go in your ui.R:

radioButtons("sample_or_real",    
    label = h4("User data or sample data?"),
    choices = list(
        "Sample Data" = "sample",
        "Upload from user data" = "user",
    ), 
    selected = "user"
)

This would go in your server.R:

data_active <- reactive({

  # if user switches to internal data, switch in-app data
  observeEvent(input$sample_or_real_button, {

  if(input$sample_or_real == "sample"){
    data_internal <- sample_data_object
  } else {
    data_internal <- uploaded_data_object
  }
})

Note, that when using a reactive value in your server.R file, it must have parentheses () at the end of the object name. So, you call the data_internal object as data_internal().

Upvotes: 2

thothal
thothal

Reputation: 20329

You can use a reactiveVal like this:

server <- function(input, output) {
   my_data <- reactiveVal()
   observeEvent(input$Upload, {
      tmp <- read.csv(input$Upload$datapath)
      ## do whatever is needed to parse the data
      my_data(tmp)
   })
   observeEvent(input$Example, {
      my_data(faithful)
   })
   output$hist <- renderPlot({
       dat <- as.data.frame(req(my_data()))
       dat <- dat[, sapply(dat, is.numeric), drop = FALSE]
       validate(need(NCOL(dat) > 1, "No numeric columns found in provided data"))
       hist(dat[,1])
   })
}

Depending on upload or button click, you store your data in my_data which is a reactive value. Whenever this value changes, the renderPlot function fires and uses the correct data.

Upvotes: 3

Related Questions