marko0o
marko0o

Reputation: 75

Crosstalk and plotly - Display only single point on hover, hide all other points

I've been playing with plotly and crosstalk and managed to link a map and chart together but I can't seem to get the formatting i'm after.

I'd like:

  1. Map to always display ALL markers
  2. When hover over map marker, display ONLY a single point within chart. Currently one point is highlighted and the other points are visible but faded. Faded points are to be removed.
  3. Chart axis to update depending depending on marker

So far I have the following code as a proof of concept:

    ---
    title: crosstalk_quake_test
    output: html_document
    --- 

    ```{r}
    library(crosstalk)
    library(plotly)  #Must use devtools::install_github("ropensci/plotly")

    Sys.setenv('MAPBOX_TOKEN' = '{insert your token here}')

    # Wrap data frame in SharedData
    sd <- SharedData$new(head(quakes,100))

    # Note - plot_mapbox does not seem to render map within RStudio but works fine in Chrome browser 
    bscols(
     plot_mapbox(sd, lat = ~lat , lon = ~long, mode = 'scattermapbox') %>% 
      layout(mapbox = list(zoom = 3,
                       center = list(lat = -22 ,lon = 179)),
       showlegend=FALSE) %>%
     highlight(on = 'plotly_hover'),
    plot_ly(data = sd, x = ~depth, y = ~mag, type = 'scatter', mode = 'markers',
       marker = list(size = 15))%>% 
      layout(showlegend = FALSE)
    )
    ```

Do I need to use shiny or can this all be done with plotly and crosstalk?

The endgame is something like: https://dash-oil-and-gas.plot.ly/

Note the map and the chart to it's right.

Upvotes: 1

Views: 1942

Answers (2)

marko0o
marko0o

Reputation: 75

I couldn't seem to get plotly / crosstalk option to do exactly what I wanted. I ended up with a plotly / shiny solution... That's not to say it can't be done with plotly / crosstalk

With this example only a single point is plotted within the chart and the axis updates appropriately

library(plotly) ##Must use devtools::install_github("ropensci/plotly")
library(shiny)

ui <- fluidPage(
  fluidRow(
    column(6, plotlyOutput(outputId = "map")),
    column(6, plotlyOutput(outputId = "chart"))),
  verbatimTextOutput("hover")
)

server <- function(input, output){

  Sys.setenv('MAPBOX_TOKEN' = '{insert your token here}')

  quake_df <- (head(quakes,100))

  # dateframe must have an ID to link on, not needed if df already has an id
  quake_df$id <- row.names(quake_df)

  # add map
  # Note - plot_mapbox does not seem to render map within RStudio but works fine in Chrome browser
  # Note - 'key = ~id'  this will be used to filter chart data 
  output$map <- renderPlotly({
    plot_mapbox(quake_df, lat = ~lat , lon = ~long, key = ~id, mode = 'scattermapbox') %>% 
      layout(mapbox = list(zoom = 3, center = list(lat = -22 ,lon = 179)), showlegend=FALSE)
  })

  # add chart
  output$chart <- renderPlotly({  

    # set hover event
    eventdata <- event_data("plotly_hover")

    # sub set of data using hover event 
    sd_sub = quake_df[quake_df$id == eventdata$key, ]  

    plot_ly(data = sd_sub, x = ~depth, y = ~mag, type = 'scatter', mode = 'markers',
            marker = list(size = 15))

  })

  # display hover output
  output$hover <- renderPrint({
    event_data("plotly_hover")
  })

}

shinyApp(ui = ui, server = server)

Upvotes: 0

user2554330
user2554330

Reputation: 44957

If you use the opacityDim = 0 argument to plotly::highlight, you'll get all points but one to disappear. That is, use this code:

bscols(
 plot_mapbox(sd, lat = ~lat , lon = ~long, mode = 'scattermapbox') %>% 
  layout(mapbox = list(zoom = 3,
                   center = list(lat = -22 ,lon = 179)),
   showlegend=FALSE) %>%
   highlight(on = 'plotly_hover'),
 plot_ly(data = sd, x = ~depth, y = ~mag, type = 'scatter', mode = 'markers',
   marker = list(size = 15))%>% 
   highlight(opacityDim = 0) %>% 
   layout(showlegend = FALSE)

I'm not sure what you want for point 3; a chart showing a single point wouldn't be much use. Do you really want to update the axes to what they'd be if only that one point was present?

If that's what you want, I don't know if you can do it with plotly. crosstalk isn't used that much, so conventions on how it should be handled haven't really solidified, but in some cases, you get the behaviour you want when the other control specifies a filtering operation instead of a highlighting operation.

Upvotes: 1

Related Questions