Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R shiny and plotly getting legend click events

Tags:

r

shiny

plotly

I have an R shiny page, and am filtering the data based on clicking a pie graph. It would be great if I could trigger the same filtering event from clicking legend entries, but I can't seem to find the event trigger, so it just filters that chart without propagating to the other charts. Is a legend click event accessible?

library(data.table)
library(plotly)
library(shiny)

dt = as.data.table(mtcars)


ui <- fluidPage(
  plotlyOutput("pie1"),
  plotlyOutput("pie2")
)


server <- function(input, output){

  gearDT = reactive({
    return(dt[,.N,by=gear])
  })

  cylDT = reactive({
    return(dt[,.N,by=cyl])
  })

  output$pie1 <- renderPlotly({

    plot_ly(gearDT(), labels = ~gear, values = ~N, type = "pie") %>%
      layout(showlegend = TRUE)


  })

  output$pie2 <- renderPlotly({

    plot_ly(cylDT(), labels = ~cyl, values = ~N, type = "pie")  %>%
      layout(showlegend = TRUE)


  })
}

shinyApp(ui = ui, server = server)
like image 470
Matt Avatar asked Nov 18 '25 16:11

Matt


2 Answers

For future readers

Plotly now has created an event called plotly_relayout. This event is triggered on layout changes. Clicking on the legend is one of these changes.

One of the variables in this event is called hiddenlabels. This variable contains all the names of the legend traces that are hidden.

observe({
    relayout <- event_data("plotly_relayout")
    hidden_labels <- relayout$hiddenlabels
    print(hidden_labels)
  })

EDIT

Check event when clicking a name in the legend of a plotly's graph in R Shiny if plotly_relayout is not working for you.

like image 194
Wilmar van Ommeren Avatar answered Nov 21 '25 06:11

Wilmar van Ommeren


Short answer is YES, but with caveats and it will take more work to implement than I will fully cover in my answer.

The plotly package includes the event_data function. In the documentation, you will find three events covered:

  1. plotly_hover
  2. plotly_click
  3. plotly_selected

The examples for using these are in the link above. They do not cover interaction with the legend specifically, rather the data in the plot proper.

However, there is the postMessage API provided by plotly, which is what shiny and other frameworks like jupyter use to capture events. I have not gone through the documentation to highlight the events relating to the legend. This would require some javascript, which you could access in R using shinyjs.

The effort may be more than you are willing to put in to achieve this directly. If it is not essential for you to go down this path then I believe you will get a better return on your time using the shiny input and reactive functions to filter and redraw.

edit with your updated example

Your edit to the question reveals a little more to your problem. Although it is not reproducible, manuf is not a colname to mtcars (I'm assuming you assigned that name to the rownames). If your legend is shared between plots, you could use a subplot grouped legend as shown in the documentation.

further revision

Pie charts behave a little strangely in subplots, see this and the docs. The following code gives you a minimal reproducible solution.

dt <- as.data.table(mtcars)

ui <- fluidPage(plotlyOutput("pie"))

server <- function(input, output){

  gearDT <- reactive({return(dt[,.N,by=gear])})  
  cylDT <- reactive({return(dt[,.N,by=cyl])})

  output$pie <- renderPlotly({

    plot_ly() %>%
      add_pie(data = gearDT(), labels = ~gear, values = ~N, name = "gear",
              domain = list(x = c(0, 0.5), y = c(0, 1))) %>%
      add_pie(data = cylDT(), labels = ~cyl, values = ~N, name = "cyl",
              domain = list(x = c(0.5, 1), y = c(0, 1))) %>%
      layout(showlegend = TRUE,
             xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
             yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))

  })

}

shinyApp(ui = ui, server = server)

And screenshot showing a common element filtered from both traces (4).

enter image description here

While your original question involved shiny and I incorporated that in my answer. The plotly chart is independent of this and would function perfectly well as an independent widget with the same functionality. Useful perhaps if you intended this in an rmarkdown document and otherwise don't need to depend on shiny.

like image 41
Kevin Arseneau Avatar answered Nov 21 '25 05:11

Kevin Arseneau