Home > Net >  Is it possible to make a plot title reactive in R Shiny?
Is it possible to make a plot title reactive in R Shiny?

Time:12-20

I have made a simple Shiny App and within the app I have a plotly drilldown chart.

Is it possible to make the plot/chart title reactive?

In this example it would be great if the title of the first plot said "GDP Level of (state you choose)"

Then, when you go to the drilldown, the title will say "GDP Level of (city you choose)"

Below is my attempt to do this. As always any and all help is appreciated.

library(tidyverse)
library(plotly)
library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(shinyjs)


full_data <- tibble(
  State = c("IL", "IL", "IL", "IL", "IL", "IL", "IN", "IN", "IN", "IN", "IN", "IN"),
  City = c("Chicago", "Rockford", "Naperville", "Chicago", "Rockford", "Naperville","Fort Wayne", 
           "Indianapolis", "Bloomington", "Fort Wayne", "Indianapolis", "Bloomington"),
  Year = c("2008", "2008", "2008", "2009", "2009", "2009", "2008", "2008", "2008", "2009", "2009", "2009"),
  GDP = c(200, 300, 350, 400, 450, 250, 600, 400, 300, 800, 520, 375)
)


ui <- fluidPage(useShinyjs(),
                selectInput(inputId = "year",
                            label = "Year",
                            multiple = TRUE,
                            choices = unique(full_data$Year),
                            selected = unique(full_data$Year)),
                selectInput(inputId = "state",
                            label = "State",
                            choices = unique(full_data$State)),
                plotlyOutput("gdp_level", height = 200),
                shinyjs::hidden(actionButton("clear", "Return to State"))
)


server <- function(input, output, session) {
  
  
  drills <- reactiveValues(
    category = NULL,
    sub_category = NULL
  )
  
  
  gdp_reactive <- reactive({
    full_data %>%
      filter(Year %in% input$year) %>%
      filter(State %in% input$state)  
  })
  
  
  gdp_reactive_2 <- reactive({
    full_data %>%
      filter(Year %in% input$year) %>%
      filter(State %in% input$state) %>%
      filter(City %in% drills$category) 
  })
  
  
  
  gdp_data <- reactive({
    
    if (!length(drills$category)) {
      
      return(gdp_reactive())
      
    }
    
    else {
      
      return(gdp_reactive_2())
      
    }
    
  })
  
  
  output$gdp_level <- renderPlotly({
    
    if(!length(drills$category))
      plot_title <- "GDP Level of State"
    else
      plot_title <- "GDP Level of City"
    
    
    gdp_data() %>% 
      plot_ly(
        x = ~Year,
        y = ~GDP,
        color = ~City,
        key = ~City,
        source = "gdp_level",
        type = "bar"
      ) %>% 
      layout(barmode = "stack", 
             showlegend = T,
             xaxis = list(title = "Year"),
             yaxis = list(title = "GDP"),
             title = plot_title)
    
  })
  
  
  
  observeEvent(event_data("plotly_click", source = "gdp_level"), {
    
    x <- event_data("plotly_click", source = "gdp_level")$key
    
    if (!length(x))
      
      return()
    
    if (!length(drills$category)) {
      
      drills$category <- x
      
    }  else {
      
      drills$sub_category <- NULL
      
    }
    
  })
  
  
  observe({
    
    if(length(drills$category))  shinyjs::show("clear")  
    
  })
  
  observeEvent(input$clear, {
    
    drills$category <- NULL
    
    shinyjs::hide("clear")
    
  })
  
}

shinyApp(ui, server)

CodePudding user response:

Using e.g. paste0 you could e.g. do plot_title <- paste0("GDP Level of ", input$state).

output$gdp_level <- renderPlotly({
  if (!length(drills$category)) {
    plot_title <- paste0("GDP Level of ",  input$state)
  } else {
    plot_title <- paste0("GDP Level of ",  input$city)
  }
  
  gdp_data() %>%
    plot_ly(
      x = ~Year,
      y = ~GDP,
      color = ~City,
      key = ~City,
      source = "gdp_level",
      type = "bar"
    ) %>%
    layout(
      barmode = "stack",
      showlegend = T,
      xaxis = list(title = "Year"),
      yaxis = list(title = "GDP"),
      title = plot_title
    )
})

enter image description here

CodePudding user response:

You just need to pass plotly's event_data to the title. The following also resets the plot after a new state was selected:

library(tidyverse)
library(plotly)
library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(shinyjs)

full_data <- tibble(
  State = c("IL", "IL", "IL", "IL", "IL", "IL", "IN", "IN", "IN", "IN", "IN", "IN"),
  City = c("Chicago", "Rockford", "Naperville", "Chicago", "Rockford", "Naperville","Fort Wayne", 
           "Indianapolis", "Bloomington", "Fort Wayne", "Indianapolis", "Bloomington"),
  Year = c("2008", "2008", "2008", "2009", "2009", "2009", "2008", "2008", "2008", "2009", "2009", "2009"),
  GDP = c(200, 300, 350, 400, 450, 250, 600, 400, 300, 800, 520, 375)
)

ui <- fluidPage(
  useShinyjs(),
  selectInput(
    inputId = "year",
    label = "Year",
    multiple = TRUE,
    choices = unique(full_data$Year),
    selected = unique(full_data$Year)
  ),
  selectInput(
    inputId = "state",
    label = "State",
    choices = unique(full_data$State)
  ),
  plotlyOutput("gdp_level", height = 400),
  shinyjs::hidden(actionButton("clear", "Return to State"))
)

server <- function(input, output, session) {
  drills <- reactiveValues(category = NULL,
                           sub_category = NULL)
  
  gdp_reactive <- reactive({
    full_data %>%
      filter(Year %in% input$year) %>%
      filter(State %in% input$state)
  })
  
  gdp_reactive_2 <- reactive({
    full_data %>%
      filter(Year %in% input$year) %>%
      filter(State %in% input$state) %>%
      filter(City %in% drills$category)
  })
  
  gdp_data <- reactive({
    if (is.null(drills$category)) {
      return(gdp_reactive())
    }
    else {
      return(gdp_reactive_2())
    }
  })
  
  output$gdp_level <- renderPlotly({
    if (is.null(drills$category)) {
      plot_title <- paste0("GDP Level of ",  input$state)
    } else {
      plot_title <- paste0("GDP Level of ",  drills$category)
    }
    
    gdp_data() %>%
      plot_ly(
        x = ~ Year,
        y = ~ GDP,
        color = ~ City,
        key = ~ City,
        source = "gdp_level",
        type = "bar"
      ) %>%
      layout(
        barmode = "stack",
        showlegend = T,
        xaxis = list(title = "Year"),
        yaxis = list(title = "GDP"),
        title = plot_title
      )
  })
  
  observeEvent(event_data("plotly_click", source = "gdp_level"), {
    x <- event_data("plotly_click", source = "gdp_level")$key
    if (is.null(x))
      return(NULL)
    if (is.null(drills$category)) {
      drills$category <- unlist(x)
    }  else {
      drills$sub_category <- NULL
    }
  })
  
  observe({
    if (!is.null(drills$category)) {
      shinyjs::show("clear")
    }
  })
  
  observeEvent(c(input$clear, input$state), {
    drills$category <- NULL
    shinyjs::hide("clear")
  })
}

shinyApp(ui, server)

result

  • Related