# Load packages
library(dplyr)
library(lubridate)
library(stringr)
library(patchwork)
library(glue)
library(ggplot2)
library(ggiraph)
# Set ggplot theme and default palette
theme_set(theme_minimal())
options(ggplot2.discrete.fill="viridis")
# Promise data
data("lakers")Problem
A ggiraph tooltip head scratcher (and the fix!)
We settled on ggiraph as our interactive visualisation package for a new Shiny dashboard. The goal was simple: capture the Y-axis value, grouped by the X-axis to display in a tooltip when a user hovers over an element. I’ve used plotly before, and it has a handy “y unified” argument that does this perfectly (see plotly reference). The hitch? ggiraph doesn’t offer that option.
The Solution: This little snag is now sorted! I’m writing this blog post to solidify the lesson for myself and hopefully save others the headache if they run into the same problem. Let’s start with the setup.
Solution
The below summaries the data and makes use of one of my favourite functions stringr::str_flatten_comma() to create the “y unified” tooltip alongside a few friends in glue & str_replace_all for my use case.
# Summarise data
ppp_top_3 <- lakers |>
filter(period != 5) |>
group_by(period, player) |>
summarise(total_points = sum(points), .groups = "drop_last") |>
slice_max(n = 3, order_by = total_points) |>
# Creating tooltip, adding <br> to neatly format tooltip
mutate(tooltip = glue(
"Total Points<br>",
str_flatten_comma(glue(" - {player} {total_points}"))
) |>
str_replace_all(",", ",<br>")) |>
ungroup()Plot prep
Before we can see the results let’s codes the plots. For those familiar with ggplot2 you’ll be able to spot the few differences. I think ggiraph's homepage provides a clean, short, and simple overview of the differences.
p <- ppp_top_3 |>
ggplot(aes(x = period, y = total_points, fill = player)) +
geom_col_interactive(position = position_dodge2()) +
labs(title = "Top 3 scoring Lakers players per period (2008-2009 Season)",
subtitle = "No Tooltip",
x = "Period",
y = "") +
theme(plot.title.position = "plot",
legend.position = "right",
legend.title = element_blank())
p_tooltip <- ppp_top_3 |>
ggplot(aes(x = period,
y = total_points,
fill = player,
tooltip = tooltip,
data_id = period)) +
geom_col_interactive(position = position_dodge2()) +
labs(subtitle = "With Tooltip",
x = "Period",
y = "") +
theme(plot.title.position = "plot",
legend.position = "right",
legend.title = element_blank())
plots <- p + p_tooltip + plot_layout(ncol = 2,
axes = "collect",
guides = "collect")Plot
Try it out!
girafe(
ggobj = plots,
options = list(
opts_hover_inv(css = "opacity:0.2"),
opts_toolbar(saveaspng = FALSE),
opts_zoom(max = 1),
opts_tooltip(
opacity = 0.8,
use_fill = TRUE,
use_stroke = FALSE,
css = "padding:5pt;color:white"
),
opts_selection(type = "none", only_shiny = FALSE),
opts_hover(css = girafe_css(
css = glue::glue("transition: all 0.5s ease;stroke: black; stroke-width: 1px;"),
text = glue::glue("fill-opacity:1;")
))
)
)Conclusion
The method of creating your tooltip in the data frame ahead of time could even work with plotly and gives you more flexibility on design.
Acknowledgements
r-bloggers.com for the reach, platform, and content
Packages and package maintainer(s):
- dplyr | Hadley Wickham
- lubridate | Vitalie Spinu
- stringr | Hadley Wickham
- patchwork | Thomas Lin Pedersen
- glue | Jennifer Bryan
- ggplot2 | Thomas Lin Pedersen
- ggiraph | David Gohel