Reputation: 935
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())
Upvotes: 0
Views: 277
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
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