Reputation: 125
I'm trying to build a Shiny app with several tabs. One of the tabs serves for the user to choose the underlying data-set and I would like this data to be displayed in nice graphs in another. (I am keeping the underlying data in files of a max. size that the user can investigate one at a time as I fear that otherwise the Shiny app might become insufferably slow or even crash). I'm struggling updating the variable holding the underlying data, however, as illustrated in the much simplified reproducible example below:
library(shiny)
library(shinyWidgets)
library(dplyr)
library(ggplot2)
dataFrameA <- data.frame(
company = c("A", "B", "C", "D"),
revenue = runif(4, min = 0, max = 1000000)
)
dataFrameB <- data.frame(
company = c("E", "F", "G", "H"),
revenue = runif(4, min = 0, max = 1000000)
)
usedDataFrame <- dataFrameA
ui <- fluidPage(
verticalTabsetPanel(
verticalTabPanel(
title = "graph", icon = icon("chart-bar", "fa-1x", lib = "font-awesome"),
box_height = "120px",
plotOutput(outputId = "barChart")
),
verticalTabPanel(
title = "data", icon = icon("database", "fa-1x", lib = "font-awesome"),
box_height = "120px",
selectInput(inputId = "selectData", label = "choose dataset",
choices = c("ABCD", "EFGH"))
)
)
)
server <- function(input, output){
output$barChart <- renderPlot({
ggplot(data = usedDataFrame, aes(x = company, y = revenue)) +
geom_bar(width = 1, stat = "identity")
})
observeEvent(input$selectData, {
if (input$selectData == "ABCD"){
usedDataFrame <- dataFrameA
}else{
usedDataFrame <- dataFrameB
}
})
}
shinyApp(ui = ui, server = server)
You will see that in spite of the user choosing a different data-set in the "data" tab the graph in the "graph" tab does not change. I would have expected it to change, however, as the observeEvent block below changes the global variable usedDataFrame that the graph is based on. Can anyone give me a hint as to how my assumption above is wrong or point out a smarter way of updating the underlying data-set? Easy explanations would help most (I don't have a technical background).
Upvotes: 0
Views: 477
Reputation: 30474
The output$barChart
is a reactive endpoint. This simplest way to modify your code is to have it use the reactive source input$selectData
directly. Whenever the input changes, your output will be notified that it needs to re-execute.
That would look like this:
output$barChart <- renderPlot({
if (input$selectData == "ABCD"){
usedDataFrame <- dataFrameA
}else{
usedDataFrame <- dataFrameB
}
ggplot(data = usedDataFrame, aes(x = company, y = revenue)) +
geom_bar(width = 1, stat = "identity")
})
And you would not need observeEvent
at all.
An alternative, you can make usedDataFrame
reactive, and call from your renderPlot
:
usedDataFrame <- reactive({
if (input$selectData == "ABCD"){
dataFrameA
}else{
dataFrameB
}
})
output$barChart <- renderPlot({
ggplot(data = usedDataFrame(), aes(x = company, y = revenue)) +
geom_bar(width = 1, stat = "identity")
})
Upvotes: 1
Reputation: 2044
You were very close to your approach but what is an easier approach than dealing with global variables can be accomplished using reactive
which will auto-update based on your input
.
library(shiny)
library(shinyWidgets)
library(dplyr)
library(ggplot2)
dataFrameA <- data.frame(
company = c("A", "B", "C", "D"),
revenue = runif(4, min = 0, max = 1000000)
)
dataFrameB <- data.frame(
company = c("E", "F", "G", "H"),
revenue = runif(4, min = 0, max = 1000000)
)
ui <- fluidPage(
verticalTabsetPanel(
verticalTabPanel(
title = "graph", icon = icon("chart-bar", "fa-1x", lib = "font-awesome"),
box_height = "120px",
plotOutput(outputId = "barChart")
),
verticalTabPanel(
title = "data", icon = icon("database", "fa-1x", lib = "font-awesome"),
box_height = "120px",
selectInput(inputId = "selectData", label = "choose dataset",
choices = c("ABCD", "EFGH"))
)
)
)
server <- function(input, output){
dat <- reactive({
if (input$selectData == "ABCD") {
return(dataFrameA)
}
else if (input$selectData == "EFGH") {
return(dataFrameB)
}
})
output$barChart <- renderPlot({
ggplot(data = dat(), aes(x = company, y = revenue)) +
geom_bar(width = 1, stat = "identity")
})
}
shinyApp(ui = ui, server = server)
Upvotes: 1