Home > Software engineering >  In R, how to use plotly's highlight() function to activate a ggplot 2 graphic layer?
In R, how to use plotly's highlight() function to activate a ggplot 2 graphic layer?

Time:06-26

I currently have the following plot and would like the regression lines from the gg_smooth() layer to only appear upon highlighting a group. I've attached the code and the plot below, hopefully someone knows if this can be done!

d <- highlight_key(happy, ~Region)

p <-ggplot( d, aes(x = Prevalence.of.current.tobacco.use....of.adults., y = Happiness.Score, group = Region, color = Region, text = Country))   
    labs(y= "Happiness Score", x = "Tobacco Use (%)", title = "Smoking and Happiness")   
    geom_smooth(aes(group=as.factor(Region)), method = "lm", se=FALSE, size=0.5)   
    geom_point(aes(size = Economy..GDP.per.Capita.))  
    theme_bw()   
    scale_color_manual(values = rainbow(10, alpha=0.6))  
    scale_size_continuous(range = c(0, 10), name='')  
    stat_cor(aes(label = ..rr.label..), color = rainbow(10), geom = "label")

gg <- ggplotly( p, tooltip = "text")

highlight( gg, on = "plotly_click", off = "plotly_doubleclick", opacityDim = .05)

enter image description here

Now that I've closely established the plot you ended with, I have to hide the lines, change the legend (since it's only showing the lines), and then set the functionality up for making the lines visible when you change the highlight or if you escape the highlight.

Remove line visibility; change the legend to reflect the points instead.

# First, make the lines invisible (because no groups are highlighted)
# Remove the line legend; add the point legend
invisible(
  lapply(1:length(gg$x$data),
         function(j){
          nm <- gg$x$data[[j]]$name
          md <- gg$x$data[[j]]$mode
          if(md == "lines") {
            gg$x$data[[j]]$visible <<- FALSE
            gg$x$data[[j]]$showlegend <<- FALSE
          } else {
            gg$x$data[[j]]$visible <<- TRUE
            gg$x$data[[j]]$showlegend <<- TRUE
          }
         }
))

You could look at the plot at this point and see the lines were no longer visible and the legend has changed a bit.

enter image description here

To add visibility changes to the highlighting, you can use Plotly events. If you know anything about HTML or Javascript, this is the same thing as an event in a browser. This uses the package htmlwidgets. I didn't call the library with the other libraries, I just appended it to the function.

Some additional information regarding the JS: The content with /* */ is a comment in Javascript. I've added these so you might follow what's happening (if you wanted to). The curveNumber in the JS is the trace number of the Plotly object. While it only has 20 traces before rendering; it has 22 afterward. While R numbers elements starting at 1, JS (like MOST languages) starts at 0.

gg %>% htmlwidgets::onRender(
  "function(el, x){
    v = [] /* establish outside of the events; used for both */
    for (i = 0; i < 22; i  ) {  /*1st 11 are lines; 2nd 11 are points */
      if(i < 12){
        v[i] = false;
      } else {
        v[i] = true;
      }
    }
    console.log(x);
    el.on('plotly_click', function(d) {
      cn = d.points[0].curveNumber - 10;  /*if [8] is the lines, [18] is the points*/
      v2 = JSON.parse(JSON.stringify(v)); /*create a deep copy*/
      v2[cn] = true;
      update = {visible: v2};
      Plotly.restyle(el.id, update); /* in case 1 click to diff highlight */
    });
    el.on('plotly_doubleclick', function(d) {
        console.log('out ', d);
        update = {visible: v}
        console.log('dbl click '   v);
        Plotly.restyle(el.id, update);
    });
  }")

The rendered view:

enter image description here

A single click from rendered

enter image description here

A single click from a single click

enter image description here

A double click from a single click

enter image description here

  • Related