show an unknown number of graphs in a grid RShiny - r

I have looked at all the solutions on SO using grid.arrange but it doesn't really achieve what I want.
Let's assume I have a list of grobs that are generated within a reactive environment in RShiny.
I would like to create a mainPanel where those graphs are on 2 columns (until that point, it's all feasible with grid.arrange) but where each line corresponds to a fluidRow element.
A barebone example of this would be
ui <- fluidPage(
titlePanel("TEST"),
sidebarPanel(width=3,
actionButton(inputId = 'launchCalcButton',label = 'Launch Calc')
),
mainPanel(
uiOutput("resultsPlotUI")
)
)
server <- function(input,output){
graphsList <- eventReactive(input$launchCalcButton, {
a <- lapply(1:10,function(i){
return(
ggplot(data = data.frame(a=rnorm(10),b=rnorm(10)),aes(x=a,y=b))
+geom_point()
)
})
return(a)
})
output$resultsPlot <- renderPlot({
do.call(grid.arrange,c(graphsList(),ncol=2))
})
output$resultsPlotUI <- renderUI({
fluidRow(
column(12,
plotOutput(
outputId = 'resultsPlot'
)
)
)
})
}
app = shinyApp(ui,server)
runApp(app)
All the graphs end up squeezed into one single line whereas I would want them to be split between lines.

You just need to set up height parameter for the plotOutput:
library(shiny)
library(gridExtra)
ui <- fluidPage(
titlePanel("TEST"),
sidebarPanel(width=3,
actionButton(inputId = 'launchCalcButton',label = 'Launch Calc')
),
mainPanel(
uiOutput("resultsPlotUI")
)
)
server <- function(input,output){
graphsList <- eventReactive(input$launchCalcButton, {
a <- lapply(1:10,function(i){
return(
ggplot(data = data.frame(a=rnorm(10),b=rnorm(10)),aes(x=a,y=b))
+geom_point()
)
})
return(a)
})
output$resultsPlot <- renderPlot({
l <- length(graphsList())/2
print(l)
do.call(grid.arrange,c(graphsList(),ncol=2))
})
output$resultsPlotUI <- renderUI({
fluidRow(
column(12,
plotOutput(
outputId = 'resultsPlot', height = 600
)
)
)
})
}
app = shinyApp(ui,server)
runApp(app)
Exactly in this place:
output$resultsPlotUI <- renderUI({
fluidRow(
column(12,
plotOutput(
outputId = 'resultsPlot', height = 600
)
)
)
})
I have set it up to 600 px (height = 600) but you can choose whatever you want.

Related

Using Conditionalpanel Function in Shiny

I'm trying to create the scenario whereby using conditionalpanel, I am able to have an user input of checked boxes to display either 1 or 2 plots, one after another.
My reproducible code can be found below, however, I am unable to display the plots.
Could someone please share with me where did I make a mistake?
library(shiny)
ui = fluidPage(
titlePanel("Plot1 or Plot2?"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("my_choices", "Plot1 or Plot2",choices = c("Plot1", "Plot2"), selected = "Plot1"),width=2),
mainPanel(
conditionalPanel(
condition = "input.my_choices == 'Plot1'",
plotOutput("plot1")
),
conditionalPanel(
condition = "input.my_choices == 'Plot2'",
plotOutput("plot2")
),
conditionalPanel(
condition = "input.my_choices.includes('Plot1', 'Plot2')",
plotOutput("plot1"),
plotOutput("plot2")
)
)
)
)
server = function(input, output) {
output$plot1 <- renderPlot({plot(iris)})
output$plot2 <- renderPlot({plot(mtcars)})
}
shinyApp(ui, server)
Update:
I've got what I wanted but without using ConditionalPanel function. Here's the code below:
Would appreciate if someone can share with me the proper way of using ConditionalPanel Function! (:
library(shiny)
#data
df <- iris
#ui
ui <- fluidPage(
sidebarPanel(
checkboxGroupInput(inputId = "Question",
label = "Choose the plots",
choices = c("Plot1", "Plot2", "Plot3"),
selected = "")),
mainPanel(
uiOutput('ui_plot')
)
)
#server
server <- function(input, output)
{
# gen plot containers
output$ui_plot <- renderUI({
out <- list()
if (length(input$Question)==0){return(NULL)}
for (i in 1:length(input$Question)){
out[[i]] <- plotOutput(outputId = paste0("plot",i))
}
return(out)
})
# render plots
observe({
for (i in 1:3){
local({ #because expressions are evaluated at app init
ii <- i
output[[paste0('plot',ii)]] <- renderPlot({
if ( length(input$Question) > ii-1 ){
return(plot(runif(100)))
}
NULL
})
})
}
})
}
shinyApp(ui, server)
I would give you an alternative as you will need to create new plots with different id in order for that to work. The simplest one I can think of is using shinyjs package and its hide and show functions. You can also do this via renderUI but you shouldn't give unnecessary work to your server only if you're showing and hiding the elements
library(shiny)
library(shinyjs)
ui = fluidPage(
useShinyjs(),
titlePanel("Plot1 or Plot2?"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("my_choices", "Plot1 or Plot2",choices = c("Plot1", "Plot2"), selected = "Plot1"),width=2),
mainPanel(
plotOutput("plot1"),
plotOutput("plot2")
)
)
)
server = function(input, output,session) {
# hide plots on start
hide("plot1");hide("plot2")
output$plot1 <- renderPlot({plot(iris)})
output$plot2 <- renderPlot({plot(mtcars)})
observeEvent(input$my_choices,{
if(is.null(input$my_choices)){
hide("plot1"); hide("plot2")
}
else if(length(input$my_choices) == 1){
if(input$my_choices == "Plot1"){
show("plot1");hide("plot2")
}
if(input$my_choices == "Plot2"){
hide("plot1");show("plot2")
}
}
else{
if(all(c("Plot1","Plot2") %in% input$my_choices)){
show("plot1");show("plot2")
}
}
},ignoreNULL = F)
}
shinyApp(ui, server)

Shiny, obtaining details from the plots

I have developed an application, where I am generating plots. I am able to render the plots and download it without any problem.
I would like to get the details of the points in the graph, when i move my cursor to the points. With search, I am not sure, if I can obtain this in Shiny.
Any help would be great.
Below is the code, i have used.
UI Code:
tabItem(tabName = "models2",
fluidPage(
fluidRow(
infoBoxOutput("overview")
),
fluidRow(
actionButton("result1","Generate Result"),
downloadButton('downloadPlot','Download Plot'),
plotOutput("plot3")
)
))
SERVER CODE
server <- function(input,output){
output$claim_overview <- renderValueBox({
valueBox(
paste("91")," Overview",icon=icon("hourglass"),
color="green"
)
})
data<- reactiveValues()
observeEvent(input$result1,{
data$plot <- ggplot(data=timedata, aes(x=dat1, y=yes, group=3))+
geom_point(shape=1)+
coord_cartesian(xlim=c(dat1_xlowlim,dat1_xhighlim))+
labs(title="Prediction Probability",x="Reg.Date",y="True probability")
})
output$plot3 <- renderPlot({ data$plot })
output$downloadPlot <- downloadHandler(
filename = function()
{paste("input$plot3",'.png',sep='')
},
content = function(file){
ggsave(file,plot = data$plot)
}
)
}
You can use either brush option or hover option to get any info from the plot.
Mouse hover example:
df<- table(rpois(100, 5))
ui <- fluidPage(
mainPanel(
plotOutput(outputId = "scatterplot", hover = "plot_hover"),
verbatimTextOutput(outputId = "dftable"),
br()
)
)
server <- function(input, output) {
output$scatterplot <- renderPlot({
plot(df, type = "h", col = "red", lwd = 10)
})
output$dftable <- renderPrint({
paste(input$plot_hover)
})
}
shinyApp(ui = ui, server = server)

R Shiny two rows by two columns

I would like to place four plots in a two rows by two columns layout. The code below returns two rows by one column. How can the second column be added?
Any help is appreciated.
ui <- shinyUI(
fluidRow(
column(6,
plotOutput(outputId = "hist1")
),
column(6,
plotOutput(outputId = "hist2")
)
)
)
server <- function(input,output){
output$hist1 <- renderPlot({
hist(rnorm(100,50,5))
})
output$hist2 <- renderPlot({
hist(rnorm(100,75,5))
})
output$hist3 <- renderPlot({
hist(rnorm(100,100,5))
})
output$hist4 <- renderPlot({
hist(rnorm(100,125,5))
})
}
runApp(list(ui = ui, server = server))
Answer from brittenb in comments : fluidPage() needs to be added.
ui <- shinyUI(
fluidPage(
fluidRow(
column(6,
plotOutput(outputId = "hist1")
),
column(6,
plotOutput(outputId = "hist2")
)
),
fluidRow(
column(6,
plotOutput(outputId = "hist3")
),
column(6,
plotOutput(outputId = "hist4")
)
)
)
)
server <- function(input,output){
output$hist1 <- renderPlot({
hist(rnorm(100,50,5))
})
output$hist2 <- renderPlot({
hist(rnorm(100,75,5))
})
output$hist3 <- renderPlot({
hist(rnorm(100,100,5))
})
output$hist4 <- renderPlot({
hist(rnorm(100,125,5))
})
}
runApp(list(ui = ui, server = server))

Dealing with loop, fluidRow and column in shiny

I'm trying to make a Shiny application that display multiple plots on different rows and allow user to select the proper tendencies by using the radioButtons situated beside the graph. The problem is that I'm not able to get the radioButtons located directly beside the plots.
I want:
And I get:
My code:
server.R:
library(shiny)
shinyServer(function(input, output) {
lapply(1:3, function(iter) {
output[[paste0("g",iter)]] <- renderPlot({
set.seed(iter)
xx <- rnorm(10)
yy <- rnorm(10)
plot(xx,yy)
abline(reg=lm(yy~xx), col=2, lwd=ifelse(input[[paste0("radio",iter)]]==1,2,1))
abline(reg=lm(yy~xx+0), col=3, lwd=ifelse(input[[paste0("radio",iter)]]==2,2,1))
})
})
})
ui.R:
library(shiny)
shinyUI(fluidPage(
titlePanel("My loop test"),
fluidRow(
column(6,
lapply(1:3, function(iter) {
plotOutput(paste0("g",iter))
}
)),
column(3,
lapply(1:3, function(iter){
radioButtons(paste0("radio",iter),label = "buttons", choices = list("with intercept"=1,"without intersept"=2),selected = 1)
}
))
)
))
I hope it's clear. I'm new to Shiny (but not R) and I'm still in the steep part of the learning curve!
Thanks
Maybe something like this:
shinyUI(fluidPage(
titlePanel("My loop test"),
lapply(1:3, function(iter) {
fluidRow(
column(
6,
plotOutput( paste0("g",iter) )
),
column(
3,
radioButtons(
paste0("radio", iter),
label = "buttons",
choices = list("with intercept"=1,"without intersept"=2),
selected = 1)
)
)
})
))
This is a good use case for modules. I didn't get the buttons to line up perfectly, but that could be fixed with some CSS:
library(shiny)
myModUI <- function(id) {
ns <- NS(id)
tagList(
fluidRow(
splitLayout(cellWidths=c("75%","25%"),
plotOutput(ns("g")),
radioButtons(ns("radio"),label = "buttons",
choices = list("with intercept"=1,"without intersept"=2),
selected = 1))
)
)
}
myMod <- function(input, output, server, seed) {
output$g <- renderPlot({
set.seed(seed)
xx <- rnorm(10)
yy <- rnorm(10)
plot(xx,yy)
abline(reg=lm(yy~xx), col=2, lwd=ifelse(input$radio==1,2,1))
abline(reg=lm(yy~xx+0), col=3, lwd=ifelse(input$radio==2,2,1))
})
return(reactive(input$radio))
}
server <- shinyServer(function(input, output, server) {
lapply(1:5,function(i) {
callModule(myMod,i,seed=i)
})
})
ui <- shinyUI(fluidPage(
titlePanel("My loop test"),
mainPanel(
lapply(1:5,function(i) {
myModUI(i)
})
)
))
shinyApp(ui=ui,server=server)
Note that fluidRow isn't enough, we have to use splitLayout

Shiny - two selectInput and one checkbox in one line

how to make 2 selectInput and one checkbox in one line, the display will be like this:
x axis : ----- y axis : ------- -check
and the code is :
UI :
library(shiny)
shinyUI(fluidPage(
titlePanel("Shiny"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
uiOutput("scatcoefgwr")
)
)
))
server :
shinyServer(function(input, output) {
output$scatcoefgwr <- renderUI({
list(
selectInput("axisx", "x axis:",choices = c("1","2","3")),
selectInput("axisy", "y axis:",choices = c("1","2","3")),
checkboxInput("scatterD3_ellipsesgwr", "check", value = FALSE)
)
})
})
Here's one way using columns
#ui.R
library(shiny)
shinyUI(fluidPage(
titlePanel("Shiny"),
fluidRow(
column(width=2,uiOutput("one")),
column(width=2,uiOutput("two")),
column(width=2,uiOutput("three"))
)
))
change the widths as you need.
#server.R
shinyServer(function(input, output) {
output$one <- renderUI({
list(
selectInput("axisx", "x axis:",choices = c("1","2","3"))
)
})
output$two <- renderUI({
list(
selectInput("axisy", "y axis:",choices = c("1","2","3"))
)
})
output$three <- renderUI({
list(
checkboxInput("scatterD3_ellipsesgwr", "check", value = FALSE)
)
})
})

Resources