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
Conditionally Change Panel Background With Facet_Grid
Ggplot, Facet, Piechart: Placing Text in the Middle of Pie Chart Slices
How to Remove Outliers from a Dataset
Why Is Rbindlist "Better" Than Rbind
Change the Blank Cells to "Na"
R Spreading Multiple Columns With Tidyr
How to Merge Color, Line Style and Shape Legends in Ggplot
Subscript Letters in Ggplot Axis Label
Split Date-Time Column into Date and Time Variables
Filtering a Data Frame on a Vector
Collapsing Rows Where Some Are All Na, Others Are Disjoint With Some Nas
Conditional Merge/Replacement in R
Error in ≪My Code≫: Target of Assignment Expands to Non-Language Object
Combining Two Data Frames of Different Lengths
Ggplot Combining Two Plots from Different Data.Frames
Replace/Translate Characters in a String
Figure Position in Markdown When Converting to Pdf With Knitr and Pandoc