Dynamically Add Plots to Web Page Using Shiny

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
)
))

dynamically add rCharts to web page using shiny

Here is how you can modify the dynamic plots example for use with hPlot. I have just replaced plotOutput with chartOutput and renderPlot with renderChart2. The rest of the changes are self-explanatory.

library(shiny); library(rCharts)
Markets = unique(someDF$Market)
server = function(input, output) {

# Insert the right number of plot output objects into the web page
output$plots <- renderUI({
plot_output_list <- lapply(1:2, function(i) {
plotname <- paste("plot", i, sep="")
chartOutput(plotname, "highcharts")
})

# 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:length(Markets)) {
# 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]] <- renderChart2({
print(my_i)
plotData = subset(someDF, Market == Markets[my_i])
print(plotData)
hPlot(Total ~ Variable.Type, data = plotData, type='pie')
})
})
}
}

ui = pageWithSidebar(
headerPanel("Dynamic number of plots"),

sidebarPanel(),

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

runApp(list(ui = ui, server = server))

Dynamically Generate Plots in Conditional Tabs using renderUI in Shiny

Your example isn't exactly minimal so i did some stripping away. First the data and helper functions

library(shiny)
library(ggplot2)

channels = c("Affiliate","Email","Media","SEO")
nObs = c(round(runif(1,100,200)))

myData = data.frame(
Campaign = unlist(lapply(channels, FUN = function(x) paste(x,seq(from=1,to=nObs,by=1),sep=""))),
Channel = rep(channels,nObs),
Return = runif(nObs*length(channels),50,500),
Spend = runif(nObs*length(channels),10,100)
)

plotSingle = function(myData, channelName){
ggplot(myData[which(myData$Channel==channelName),], aes(x = Spend, y = Return)) +
geom_point(color="black") +
theme(panel.background = element_rect(fill = 'grey85'),
panel.grid.major = element_line(colour = "white"))
}

Now the UI

ui <- fluidPage(
headerPanel('Plot Testing'),
mainPanel(
uiOutput('mytabs'),
plotOutput('scatterPlot')
)
)

Note that we only use one plotOutput here. What we will do is just change the plot it's showing based on the currently selected tab. Here's the server code

server = function(input, output) {

rawData <- reactive({
myData
})

output$mytabs = renderUI({
if(is.null(rawData())){return ()}
channels = unique(rawData()$Channel)
myTabs = unname(Map(tabPanel, channels))
do.call(tabsetPanel, c(myTabs, id="channeltab"))
})

output$scatterPlot <- renderPlot({
if(is.null(rawData()) | is.null(input$channeltab)){return ()}
plotSingle(rawData(), input$channeltab)
})

}

You see we set an id on the tabsetPanel we create. We can then use that as input to determine which panel is selected and show the correct plot. All run with

shinyApp(ui = ui, server = server)

Dynamically create plots based on number of uploaded files in Shiny

I could get it to work. One has to use a reactive conductor to create the plots, as explained here

shinyServer(function(input, output) {

createPlots <- reactive ({
numberOfFiles <- length(input$files$datapath)
for (i in 1:numberOfFiles) {
local({
my_i <- i
plotname <- paste("plot", my_i, sep="")
File <- read.csv(input$files$datapath[my_i])
output[[plotname]] <- renderPlot({
result <- runDensity(File, f)
plot(result$data, main=id, pch=19,cex=0.2, col= ColoursUsed[result$clusters])
})
})
}
})

output$densityPlot <- renderUI({

inFile <- input$files
if (is.null(inFile))
return(NULL)
createPlots()
numberOfFiles <- length(inFile$datapath)
plot_output_list <- lapply(1:numberOfFiles, function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname)
})

do.call(tagList, plot_output_list)
})

})

shiny dynamically add input fields and data without getting re-rendered

You should consider using modules and insertUI / removeUI. Clicking on the buttons will not reset your changes on the inputs you already called. Here, you just have inputs so you only need to call the function add_box I created, but if you want to add outputs in the module, then you will need to use the function callModule in observeEvent. This is explained in the article I refer to.

This is not the method you suggested but it works.

library(shiny)

dist <- c("Normal", "Gamma")

add_box <- function(id){
ns <- NS(id)
tags$div(id = paste0("new_box", id),
selectInput(inputId = ns("news"),
label = paste0("Variable ", id),
choices = dist),

conditionalPanel(
condition = "input.news=='Normal'",
ns = ns,
textInput(ns("txt"), "Text input:", paste0("var", id)),
column(width = 3, numericInput(ns('normal_mean'), 'Mean', value = '0')),
column(width = 3, numericInput(ns('normal_sd'), 'Standard deviation', value = '1'))),

conditionalPanel(
condition = "input.news=='Gamma'",
ns = ns,
textInput(ns("txt"), "Text input:", paste0("var", id)),
column(width = 3, numericInput(ns('gamma_shape'), 'Shape', value = '0')),
column(width = 3, numericInput(ns('gamma_scale'), 'Scale', value = '1')))
)
}


ui <- shinyUI(fluidPage(

sidebarPanel(

actionButton("add_btn", "Add Textbox"),
actionButton("rm_btn", "Remove Textbox"),
textOutput("counter")

),

mainPanel(column(width = 12, id = "column"))

))

server <- shinyServer(function(input, output, session) {

# Track the number of input boxes to render
counter <- reactiveValues(n = 0)

# Track all user inputs
AllInputs <- reactive({
x <- reactiveValuesToList(input)
})

observeEvent(input$add_btn, {
counter$n <- counter$n + 1
insertUI(selector = "#column",
where = "beforeEnd",
ui = add_box(counter$n)
)
})

observeEvent(input$rm_btn, {
if (counter$n > 0) {
removeUI(selector = paste0("#new_box", counter$n))
counter$n <- counter$n - 1
}
})

output$counter <- renderPrint(print(counter$n))


})

shinyApp(ui, server)


Related Topics



Leave a reply



Submit