Reputation: 356
I'm attempting to display multiple plots in my main panel in my Shiny app.
I am using the multiplot function from R cookbook
multiplot <- function(..., plotlist=NULL, file, cols=1, layout=NULL) {
library(grid)
# Make a list from the ... arguments and plotlist
plots <- c(list(...), plotlist)
numPlots = length(plots)
# If layout is NULL, then use 'cols' to determine layout
if (is.null(layout)) {
# Make the panel
# ncol: Number of columns of plots
# nrow: Number of rows needed, calculated from # of cols
layout <- matrix(seq(1, cols * ceiling(numPlots/cols)),
ncol = cols, nrow = ceiling(numPlots/cols))
}
if (numPlots==1) {
print(plots[[1]])
} else {
# Set up the page
grid.newpage()
pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout))))
# Make each plot, in the correct location
for (i in 1:numPlots) {
# Get the i,j matrix positions of the regions that contain this subplot
matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE))
print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row,
layout.pos.col = matchidx$col))
}
}
}
And then calling multiplot
multiplot(p1,p2,p3,p4,p5,p6, cols=1)
But it looks like it's trying to squish everything in to the main panel
Here is what my app looks like with only one plot
Here is my ui.R
shinyUI(fluidPage(
titlePanel("Baseball"),
sidebarLayout(
sidebarPanel(
selectInput(
"var", label = "Choose a group to visualize",
choices =c(Overall = "overall", Offense = "offense", Pitchers = "pitchers", Simpsons = "simpsons"),
selected = "offense")
),
mainPanel(
plotOutput("plotOffense")
)
)
)
)
Do I need to be using something instead of mainPanel that allows for more graphics to be placed in the browser?
Upvotes: 3
Views: 8197
Reputation: 32446
Well, there are really just two things that have to happen: plotOutput
should be called to create the div for the actual output, and renderPlot
needs to be called to format the plot in the correct way. So, here are a some functions that can do this dynamically, and let you play with the width/height/number of columns, similar to the multiplot, only in a shiny way. Refer to this gist as well.
I separated things into functions, but it could be just put straight into the server function as well.
EDIT: I forgot to mention, the width and height entry boxes are text, and should be valid CSS, so it could be 10, 10px, or 10% for example.
library(shiny)
library(ggplot2)
## Some sample data
dat <- setNames(data.frame(matrix(runif(100),10)), letters[1:10])
dat$time <- seq(nrow(dat))
## Make some random plots because it looks cooler
## But you would just define your 10 different plots
rndmPlot <- function(input)
sample(list(geom_line(), geom_bar(stat='identity'), geom_point(), geom_jitter(),
geom_density(aes_string(x=input$var), inherit.aes=FALSE)), 1)
makePlotContainers <- function(n, ncol=2, prefix="plot", height=100, width="100%", ...) {
## Validate inputs
validateCssUnit(width)
validateCssUnit(height)
## Construct plotOutputs
lst <- lapply(seq.int(n), function(i)
plotOutput(sprintf('%s_%g', prefix, i), height=height, width=width))
## Make columns
lst <- lapply(split(lst, (seq.int(n)-1)%/%ncol), function(x) column(12/ncol, x))
do.call(tagList, lst)
}
renderPlots <- function(n, input, output, prefix="plot") {
for (i in seq.int(n)) {
local({
ii <- i # need i evaluated here
## These would be your 10 plots instead
output[[sprintf('%s_%g', prefix, ii)]] <- renderPlot({
ggplot(dat, aes_string(x='time', y=input$var)) + rndmPlot(input)
})
})
}
}
ui <- shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput('nplots', 'Number of Plots', min=1, max=10, value=8),
selectInput("var", label = "Choose", choices=letters[1:10]),
textInput('height', 'Plot Height', value="100"),
textInput('width', 'Width', value="100%"),
sliderInput('ncol', 'Columns', min=1, max=3, value=2)
),
mainPanel(
uiOutput('plots')
)
)
)
)
server <- shinyServer(function(input, output) {
output$plots <- renderUI({
makePlotContainers(input$nplots, ncol=input$ncol, height=input$height, width=input$width)
})
observeEvent(input$nplots, renderPlots(input$nplots, input, output))
})
shinyApp(ui, server)
Upvotes: 10