Shiny R Renderplots on the Fly

Shiny R renderPlots on the fly

If anyone's still interested in an answer, try this:

library(shiny)

runApp(shinyApp(

ui = shinyUI(
fluidPage(
numericInput("number", label = NULL, value = 1, step = 1, min = 1),
uiOutput("plots")
)
),

server = function(input, output) {

### This is the function to break the whole data into different blocks for each page
plotInput <- reactive({
n_plot <- input$number
total_data <- lapply(1:n_plot, function(i){rnorm(500)})
return (list("n_plot"=n_plot, "total_data"=total_data))
})

##### Create divs######
output$plots <- renderUI({
plot_output_list <- lapply(1:plotInput()$n_plot, function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname, height = 280, width = 250)
})
do.call(tagList, plot_output_list)
})

observe({
lapply(1:plotInput()$n_plot, function(i){
output[[paste("plot", i, sep="") ]] <- renderPlot({
hist(plotInput()$total_data[[i]], main = paste("Histogram Nr", i))
})
})
})
}

))

R/shiny: render elements of plots only when needed in shiny apps

So maybe try grDevices, like here:

server.R:

library("shiny")
library("grDevices")

data(iris)
plot(x=NA, y=NA, xlim=c(0,10), ylim=c(0,10))
p <- recordPlot()

function(input, output, session) {

output$plotPoints <- renderPlot({
replayPlot(p)
points(1:input$ile)
})
}

and ui.R:

library(shiny)

fluidPage(
sidebarPanel(
sliderInput("ile", min=1, max=10, label="", value=5)
),
mainPanel(
plotOutput("plotPoints"))
)

Plot the Plotly Graph Dynamically in the Shiny App in R

This was more complicated than it looked. It looks like you want to iterate and create a series of plotly graphs, changing the data values as you go along.

Because the Generations slider re-initializes the vector to a new length,
and each iteration changes the state of the data being plotted, you can't just cascade reactive functions. Storing the state in a reactiveValues is a good way to handle this.

The major changes were as follows:

  • Added a reactiveValues to store xAxis and yAxis
  • Added an observeEvent to reinitialize those values when its value change
  • Added an "Iteration range" slider to drive the iteration (easier than a reactive timer). Note that it has an animate parameter that (probably) creates a reactive timer on its own.
  • Modified the plotly call to make it more conventional and avoid warnings.

The code:

library(shiny)
library(plotly)

u <- fluidPage(
titlePanel("Iterations of a plotly graph"),
sidebarLayout(
sidebarPanel(
sliderInput("Generations","Number of Generations:",
min = 1, max = 50, value = 20),
sliderInput("iter", "Iteration range:",
value = 1, min = 1, max = 1000, step = 1,
animate=animationOptions(interval=800, loop=T)),
p("To start click on the blue arrowhead")
),
mainPanel(
plotlyOutput("GA")
)
))
s <- shinyServer(function(input,output){

rv <- reactiveValues(xAxis=NULL,yAxis=NULL)

observeEvent(input$Generations,{
rv$xAxis=vector("numeric", as.numeric(input$Generations))
rv$yAxis=vector("numeric", as.numeric(input$Generations))
})
output$GA = renderPlotly({
rv$yAxis[input$iter] <- input$iter
rv$xAxis[input$iter] <- input$iter
gdf <- data.frame(xAxis=rv$xAxis, yAxis=rv$yAxis)
plot_ly(gdf, x = ~xAxis, y = ~yAxis, type="scatter",mode="markers")
})
})
shinyApp(u,s)

Because it is dynamic, you have to run it to see how it really works, but here is a screen shot after several iterations:

Sample Image

Clicking through plots in Shiny app

You just need to use the variable that will maintain the count for each click:

    library(shiny)
server <- function(input, output, session) {
# data
v <- c(9,8,7,8,9,5,6,7,4,3)
w <- c(3,4,2,3,3,3,2,3,4,5)
x <- c(1,3,4,6,2,4,6,8,6,3)
y <- c(4,5,2,4,2,1,2,5,7,8)
z <- c(5,9,8,6,4,6,8,9,6,7)
df <- data.frame(v, w, x, y, z)

# initial plot that will allow user to change parameters (haven't implemented yet)
output$plot <- renderPlot(plot(df[[1]],df[[2]]))

count<-0 # This is the counter which keeps track on button count

observeEvent(input$run, {
count <<- count + 1 # Increment the counter by 1 when button is click
if(count<6){
# Draw the plot if count is less than 6
output$plot <- renderPlot(plot(df[[1]],df[[count]],main = count))
}
else{
# Reset the counter if it is more than 5
count <- 0
}
})
}

ui <- fluidPage(
actionButton("run", "Generate"),
plotOutput("plot")
)

shinyApp(ui = ui, server = server)

dynamically add plots to web page using shiny

Perhaps this example due to Winston Chang is helpful:

Shiny example app with dynamic number of plots

Here is the full example just in case of linkrot:

server.R

max_plots <- 5

shinyServer(function(input, output) {

# Insert the right number of plot output objects into the web page
output$plots <- renderUI({
plot_output_list <- lapply(1:input$n, function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname, height = 280, width = 250)
})

# Convert the list to a tagList - this is necessary for the list of items
# to display properly.
do.call(tagList, plot_output_list)
})

# Call renderPlot for each one. Plots are only actually generated when they
# are visible on the web page.
for (i in 1:max_plots) {
# Need local so that each item gets its own number. Without it, the value
# of i in the renderPlot() will be the same across all instances, because
# of when the expression is evaluated.
local({
my_i <- i
plotname <- paste("plot", my_i, sep="")

output[[plotname]] <- renderPlot({
plot(1:my_i, 1:my_i, xlim = c(1, max_plots), ylim = c(1, max_plots), main = paste("1:", my_i, ". n is ", input$n, sep = ""))
})
})
}
})

ui.R

shinyUI(pageWithSidebar(

headerPanel("Dynamic number of plots"),

sidebarPanel(
sliderInput("n", "Number of plots", value=1, min=1, max=5)
),

mainPanel(
uiOutput("plots") # This is the dynamic UI for the plots
)
))

Update dynamically created plot in R Shiny

I can dynamically generate any compound ui, as I can create named inputs and outputs dynamically and then they respond to events as usual.

#ui.R
library(shiny)

# Define UI for application that plots random distributions
shinyUI(pageWithSidebar(

headerPanel("Example"),

# Sidebar with a slider input for number of observations
sidebarPanel(
checkboxInput("show_dynamic_ui", label="Show dynamic UI", value=TRUE)
),

# Show a plot of the generated distribution
mainPanel(
uiOutput("dynamic_ui")
)
))

#server.R
library(shiny)

shinyServer(function(input, output, session) {

output$dynamic_ui <- renderUI({
if (input$show_dynamic_ui) #NULL when not checked
fluidPage(
fluidRow(column(6, sliderInput("dinput", "Number of observations:",min=1, max=1000, value=500))),
fluidRow(column(12, plotOutput("dplot")))
)
})

output$dplot<-renderPlot({
dist <- rnorm(as.integer(input$dinput))
hist(dist)
})
})

Plot by variable in Shiny

I am not sure this is what you are looking for, but hope this will help.

Instead of multiple if statements, you can just make sure the input$var selected is one of the 3 variables of interest (sex, intubated, or support). isolate is included so the plot is not automatically redrawn, until input$go is selected as you currently have it.

You can use aes_string and pass in input$var which has the character value of the column you wish to plot. If you want the line plots with counts, you can use geom_line(stat = 'count').

server <- function(input, output) {

dataInput <- reactive({
subset(data_n, date >= input$range[1] & date <= input$range[2])
})

plotInput <- eventReactive(input$go, {
if (c(isolate(input$var)) %in% c("sex", "intubated", "support")) {
ggplot(data = dataInput(), aes_string(x = "date", group = input$var, color = input$var)) +
geom_line(stat = 'count')
}
})

output$plot_neo <- renderPlot({
plotInput()
})

}


Related Topics



Leave a reply



Submit