Skip to content

Instantly share code, notes, and snippets.

@jimjam-slam
Last active January 19, 2024 15:00
Show Gist options
  • Save jimjam-slam/1d988451ae15882c889f49cf20b99a64 to your computer and use it in GitHub Desktop.
Save jimjam-slam/1d988451ae15882c889f49cf20b99a64 to your computer and use it in GitHub Desktop.
How to add SVG attributes to a ggplot to assist in building interactives for the web #rstatstips
# gridSVG::grid.garnish can be used to add SVG attributes to elements of a plot!
# we don't even need to do it one at a time: with the option `group = FALSE`, we
# can give it a vector of values for an attribute and garnish an entire geom at
# once. the only rub is that sometimes ggplot2 shuffles your data around when
# plotting it. we need to check how the data was reordered, and arrange our
# original data to match, before we send it to grid.garnish.
library(tidyverse)
library(magrittr)
library(grid)
library(gridExtra)
library(gridSVG)
select = dplyr::select
filter = dplyr::filter
# step 1: create the plot. i've left out the analysis code here, but i have
# a data frame, `mts_data`, with the columns `year`, `count` and `anomaly`.
hb_theme = theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.y = element_line(colour = "#666666"),
axis.title.x = element_text(colour = 'white', margin = margin(t = 9)),
axis.text = element_text(colour = "#666666"),
plot.subtitle = element_text(colour = '#666666'),
plot.title = element_text(colour = '#999999'))
mts_barplot = ggplot(mts_data) +
geom_col(
aes(x = year, y = anomaly),
fill = 'white', colour = NA, show.legend = FALSE) +
theme_minimal(base_family = 'Oswald', base_size = 14) +
hb_theme +
labs(
x = 'YEAR',
y = NULL,
title = 'AUSTRALIAN AVERAGE NIGHTS OVER 20 °C EACH YEAR',
subtitle = 'RELATIVE TO THE 1940–2013 AVERAGE (101.65 PER YEAR)')
# step 2: sort the data frame by the order in which ggplot2 plots them.
# occasionally ggplot2 reorders data during plotting (eg. here it plots ngative bars first,
# then positive ones). since this is the order the grid elements appear, any data we pass
# to grid.garnish needs to match it!
# nb: this data frame uses the names of the aesthetics for columns, not the names of the source
# columns
plotted_data =
ggplot_build(mts_barplot)$data %>%
# nb: if you have multiple geoms, you might need to group them first!
mutate(plot_order = 1:nrow(.)) %>%
select(plot_order, x, y)
mts_data %<>%
inner_join(plotted_data, by = c("year" = "x", "anomaly" = "y") %>%
arrange(plot_order)
# step 3: send the plot to the graphics device, add your extra SVG info to it, and export
barplot_grob = mts_barplot %>% ggplotGrob() %>% grid.force()
dev.new(width = 8, height = 4.5, units = 'in')
grid.draw(barplot_grob)
# grid.garnish needs a handle
grid.garnish('geom_rect',
'class' = paste0('chart_bar_', if_else(mts_data$anomaly > 0, 'pos', 'neg')),
'data-year' = mts_data$year,
'data-count' = mts_data$count,
'data-anomaly' = mts_data$anomaly,
group = FALSE, grep = TRUE, redraw = TRUE)
grid.export('garnish_barchart.svg', strict = FALSE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment