Reputation: 446
For a Shiny app that I am working on, given a data file, I need to display a barplot (for which I am using ggplot2) on the starting page of the app. So when the user runs the app, and uploads a file, they would immediately get to see the barplot in main panel.
After the app has started, the user should be able to click an actionButton to bootstrap the data and add error bars to the same barplot. I don't want to add the error bars to start with, because my users might not be interested in the error bars and adding error bars with bootstrapping would keep them waiting. So, I must add the error bars only if they want to see it and are willing to wait for bootstrapping to be over.
I tried many ways to update the plot but haven't been successful. I could of course render another plot with the error bars but it is not what I would like to do ideally. Is there a way to update plots or add features to them?
Upvotes: 3
Views: 11878
Reputation: 121
I tried doing this in shiny using Plotly but without layers as shown above. Although this may be an old thread, it may be helpful for others.
In the following example:
library(shiny)
library(plotly)
ui <- fluidPage(
selectizeInput(
inputId = "Player",
selected = NULL,
multiple = TRUE,
label = " Choose Player",
choices = c("Sam", "Bennet", "Orlando"),
options = list('plugins' = list('remove_button'))
),
plotlyOutput("Plot1")
)
server <- function(input, output, session) {
output$Plot1 <- renderPlotly({
scores <- data.frame(Name = c("Sam", "Bennet", "Orlando", "Sam", "Bennet", "Orlando", "Sam", "Bennet", "Orlando" ),
Number= c(47, 35, 40, 49, 32, 31, 51, 49, 44 ),
Year = c("2018","2018","2018", "2017", "2017", "2017", "2016","2016","2016")
)
chris_goals <- data.frame(Name = c("Chris", "Chris", "Chris"),
Number= c(90, 95, 100 ),
Year = c("2018","2017","2016")
)
filteredScores <- reactive({
plot_ly(chris_goals, x = ~Year, y = ~Number, type = 'scatter', mode = 'lines', color = ~Name)%>% layout(showlegend = TRUE) %>%
layout(title = 'Scores') %>%
add_trace(data = scores[scores$Name %in% input$Player, ], x = ~Year, y = ~Number, type = 'scatter', mode = 'lines', color = ~Name)
})
filteredScores()
})
}
shinyApp(ui, server)
Upvotes: 0
Reputation: 4467
I think that you always will have to go through renderPlot
in order to update the plot output (unless you save the plot as a image, and load it on-top of your plot within an invisible div or something like this). What you could do is save the layers of your plot separately splitting it into 2 part, one with the bar plot and one with the error bar and then just layer the error bars on top if need be.
data(iris)
require(shiny)
sepal.length <- sapply(unique(iris$Species),function(s){ iris[which(iris$Species==s),"Sepal.Length"] })
data <- data.frame("mean"=apply(sepal.length,2,mean),"sd"=apply(sepal.length,2,sd),"species"=unique(iris$Species))
server <- shinyServer(function(input, output, session) {
# Save plot in reactive
plot.dat <- reactiveValues(main=NULL, layer1=NULL)
plot.dat$main <- ggplot(data=data,aes(x=species,y=mean,fill=species)) +
geom_bar(stat="identity")
observe({
print("render")
output$plot <- renderPlot({ plot.dat$main + plot.dat$layer1 })
})
observeEvent(input$add_bars,{
# Calculate standard deviation
plot.dat$layer1 <- geom_errorbar(aes(ymin=mean-sd,ymax=mean+sd))
})
})
ui <- shinyUI(fluidPage(
plotOutput("plot"),
actionButton("add_bars","Add error bars")
))
shinyApp(ui = ui, server = server)
Upvotes: 2