0

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

Tingolfin
  • 825
  • 8
  • 28

2 Answers2

2

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)
MLavoie
  • 9,671
  • 41
  • 36
  • 56
  • Thank you for the answer. I'd like to keep the legend though, so option 2 would be preferable. But it seems that one doesn't work with ggplot2 and I'd like to have all the customization options that the package offers. I suppose there's no way to combine both? – Tingolfin Mar 02 '18 at 13:05
  • 1
    @Tingolfin. I think you will have to decide. Plotly and ggplot are not always working well together. – MLavoie Mar 02 '18 at 13:10
  • Hmm that's too bad, but thanks a lot for your answers! I might look for another way to get info on the square point by hovering (it that exists). – Tingolfin Mar 02 '18 at 13:22
0

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!

Tingolfin
  • 825
  • 8
  • 28