Tingolfin
Tingolfin

Reputation: 935

plotly: possible to make only certain graphical objects interactive?

I have a ggplot I'd like to turn interactive. However, I don't want ALL of the objects to be interactive as some are actually made to serve as a kind of background drawing (in this case, rows of greenhouse plants). The data in the squares on top of it should be interactive, but not the green plant dots or grey rows.

Is this even possible with plotly? And if so: how?

My code and result (I added theme_update() so the reproduction would look exactly like mine, although it's less important):

Code

    # counts in greenhouse 
Wtot <- c(10,65,139,87) 
plant <- c(15,15,30,30) 
row <- c(10,20,10,20) 
df <- data.frame(Wtot,plant,row)

    # df for greenhouse background 
nrows = 40 
nplants = 50 
greenh <- data.frame(   
  Row <- rep(1:nrows, each=nplants),   
  Plant <- rep(1:nplants, times=nrows),   
  Plantnr <- paste("plant",1:(nrows*nplants)) 
)

    # plottheme
theme_set(theme_bw()) 
theme_update(axis.title.x = element_text(size = 16, colour = 'black'),
             axis.title.y = element_text(size = 16, colour = 'black', angle = 90),
             axis.text.x = element_text(size = 12, colour = 'black'),
             axis.text.y = element_text(size = 12, colour = 'black'),
             legend.text = element_text(size = 14, colour = 'black'),
             legend.title = element_blank(),
             legend.position = "right",
             legend.box = "vertical",
             strip.text.x = element_text(size = 14, colour = 'black'),
             strip.text.y = element_text(size = 14, colour = 'black', angle = -90),
             panel.background = element_rect(fill = "gray94"),
             panel.grid.minor = element_blank(),
             panel.grid.major = element_blank())

    # plot 
p <- ggplot(data=df, aes(row, plant, colour=Wtot)) +   
   xlim(0,nrows) +   
   ylim(0,nplants) +   
   coord_equal() +   
   geom_vline(xintercept=1:nrows, colour="darkgrey", alpha=0.5, size=0.7) +    
   geom_point(data=greenh, aes(x=Row, y=Plant), colour="darkgreen", alpha=0.3) +  
   geom_point(aes(fill=Wtot, size=Wtot), colour="black", pch=22) +  
   scale_fill_gradient2(low="green", mid="yellow", high="red", na.value="grey", 
                           limits=c(0,300), midpoint=150, breaks=c(0,75,150,225,300)) +   
   scale_size_continuous(range=c(3,6), limits=c(0,300), breaks=c(0,75,150,225,300)) +    
   guides(fill=guide_legend(), size = guide_legend())

Graph enter image description here

Upvotes: 0

Views: 277

Answers (2)

Tingolfin
Tingolfin

Reputation: 935

So I have found the solution and also figured I left out quite critical information: I'm using this interactive plot in a flexdashboard. I left out that part to keep the example simple, but apparently it held the key!

The answer on this question got me on the right track: How do I show the y value on tooltip while hover in ggplot2

When using shiny functions plotOutput() and renderPlot() you can add a hover-function via the argument hover = in plotOutput. Flexdashboards do not have a seperate ui and server part, so plotOutput() is not used. This means you need to specify the hover options seperately and then add them to renderPlot() via the argument outputArgs = (more info: https://shiny.rstudio.com/articles/output-args.html).

 # specify hover details
 HO <- hoverOpts(id = "plot_hover", delay = 300, delayType = c("debounce", "throttle"), 
                 clip = TRUE, nullOutside = TRUE)

 # reactive plot function
 renderPlot({
 ggplot(data=df, aes(row, plant, colour=Wtot)) +   
   xlim(0,40) +   
   ylim(0,50) +   
   coord_equal() +   
   geom_vline(xintercept=1:nrows, colour="darkgrey", alpha=0.5, size=0.7) +    
   geom_point(data=greenh, aes(x=Row, y=Plant), colour="darkgreen", alpha=0.3) +  
   geom_point(aes(fill=Wtot, size=Wtot), colour="black", pch=22) +  
   scale_fill_gradient2(low="green", mid="yellow", high="red", na.value="grey", 
                           limits=c(0,300), midpoint=150, breaks=c(0,75,150,225,300)) +   
   scale_size_continuous(range=c(3,6), limits=c(0,300), breaks=c(0,75,150,225,300)) +    
   guides(fill=guide_legend(), size = guide_legend())
}, outputArgs = list(hover = HO)) # include hover options

Now the plot is ready to show hover info, but it doesn't show anything yet. You have to specify which info you'd like to see. And HERE I can tell it to only show info of the squares and not of the greenhouse elements:

# shown hover results
renderPrint({ 
  hover <- input$plot_hover
  y <- nearPoints(df, input$plot_hover)
  req(nrow(y) != 0)
  y
})

You can tweak the code further to show the info as a tooltip (see thread mentioned above).

I hope this may be of help to other people!

Upvotes: 0

MLavoie
MLavoie

Reputation: 9836

You have a couple of options:

Option 1: Using ggplotly you will lose your legend. But you will have to add your points manually.

 # p <- ggplot(data=df, aes(row, plant, colour=Wtot)) +   
   p <- ggplot(data=greenh, aes(x=Row, y=Plant)) + 
   xlim(0,nrows) +   
   ylim(0,nplants) +   
   coord_equal() +   
   geom_vline(xintercept=1:nrows, colour="darkgrey", alpha=0.5, size=0.7) +    
   geom_point(colour="darkgreen", alpha=0.3) +  
  #geom_point(aes(fill=Wtot, size=Wtot), colour="black", pch=22) +  
   scale_fill_gradient2(low="green", mid="yellow", high="red", na.value="grey", 
                         limits=c(0,300), midpoint=150, breaks=c(0,75,150,225,300)) +   
   scale_size_continuous(range=c(3,6), limits=c(0,300), breaks=c(0,75,150,225,300)) +    
   guides(fill=guide_legend(), size = guide_legend())

  pp <- ggplotly(p, tooltip = "none")
  pp %>% add_markers(x = c(10, 20, 10, 20), y = c(15, 15, 30, 30), color = I("green"), text = c(10, 65, 139, 87), symbol = I('square'), marker = list(size = c(14, 13, 15, 12)))

Option 2: Using plot_ly you can get something similar with a legend. You just have to set your colors and sizes as you want.

plot_ly(data=greenh, x=~Row, y= ~Plant) %>% 
add_markers(showlegend = FALSE, color = I("green"), hoverinfo = "none") %>% 
add_markers(data=df, x=~row, y= ~plant, showlegend = TRUE, color = ~ Wtot, size = ~ Wtot)

Upvotes: 2

Related Questions