Search code examples
rshinyplotlyggplotly

Formatting Shiny Plotly subplots - Individual titles and graph size


I'm trying to provide individual titles for each of my graphs within plotly's subplot function and I found a post where you can extend subplot using %>% layout(title = "Main Title) but I'd like individual titles for each graph (I'm using ggtitle but that only plots the last title provided (Plot 4). I found a similar post Provide title to each of the subplots - R Shiny but I don't think that I can facet_wrap in my scenario.

Furthermore - I was wondering how to increase the margin between the graphs in a subplot since they seemed to be really squished together.

Any help appreciated!

enter image description here

ui <- fluidPage(
  sidebarPanel("This is a sidebar"),
  mainPanel(plotlyOutput("myplot"))
    )

server <- function(input, output){

  output$myplot <- renderPlotly({

    gg1 <- ggplotly(
      ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) + 
        geom_point() +
        theme_minimal() +
        ggtitle("Plot 1")
    )

    gg2 <- ggplotly(
      ggplot(iris, aes(x=Species, y=Sepal.Length)) +
        geom_boxplot() +
        theme_minimal() +
        ggtitle("Plot 2")
    )

    gg3 <- ggplotly(
      ggplot(iris, aes(x=Petal.Width)) +
        geom_histogram() +
        ggtitle("Plot 3")
    )

    gg4 <- ggplotly(
      ggplot(iris, aes(x=Petal.Length)) +
        geom_histogram() +
        ggtitle("Plot 4")
    )

    subplot(list(gg1,gg2,gg3,gg4), nrows = 2)
  })
}

shinyApp(ui = ui, server = server)

Solution

  • As already mentioned by @Edo subplot titles are an open issue regarding R's plotly api. Currently we need to use annotations. Here is an official example.

    The subplot function provides us with an argument margin to add some space.

    library(shiny)
    library(plotly)
    
    ui <- fluidPage(
      sidebarPanel("This is a sidebar"),
      mainPanel(plotlyOutput("myplot"))
    )
    
    server <- function(input, output, session){
    
      output$myplot <- renderPlotly({
    
        gg1 <- ggplotly(
          ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) + 
            geom_point() +
            theme_minimal()
        ) %>% add_annotations(
          text = "Plot 1",
          x = 0,
          y = 1,
          yref = "paper",
          xref = "paper",
          xanchor = "left",
          yanchor = "top",
          yshift = 20,
          showarrow = FALSE,
          font = list(size = 15)
        )
    
        gg2 <- ggplotly(
          ggplot(iris, aes(x=Species, y=Sepal.Length)) +
            geom_boxplot() +
            theme_minimal()
        ) %>% add_annotations(
          text = "Plot 2",
          x = 0,
          y = 1,
          yref = "paper",
          xref = "paper",
          xanchor = "left",
          yanchor = "top",
          yshift = 20,
          showarrow = FALSE,
          font = list(size = 15)
        )
    
        gg3 <- ggplotly(
          ggplot(iris, aes(x=Petal.Width)) +
            geom_histogram()
        ) %>% add_annotations(
          text = "Plot 3",
          x = 0,
          y = 1,
          yref = "paper",
          xref = "paper",
          xanchor = "left",
          yanchor = "top",
          yshift = 20,
          showarrow = FALSE,
          font = list(size = 15)
        )
    
        gg4 <- ggplotly(
          ggplot(iris, aes(x=Petal.Length)) +
            geom_histogram()
        ) %>% add_annotations(
          text = "Plot 4",
          x = 0,
          y = 1,
          yref = "paper",
          xref = "paper",
          xanchor = "left",
          yanchor = "top",
          yshift = 20,
          showarrow = FALSE,
          font = list(size = 15)
        )
    
        subplot(list(gg1,gg2,gg3,gg4), nrows = 2, margin = 0.06)
      })
    }
    
    shinyApp(ui = ui, server = server)
    

    Result

    By the way you can use schema() to browse through plotly's attributes.