Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Replace categorical x-axis labels with images
#' Replace categorical x-axis labels with images
#' Pipe a ggplot2 graph (with categorical x-axis) into this function with the argument of a list of
#' pictures (e.g. loaded via readImage) and it builds a new grob with the x-axis categories
#' now labelled by the images. Solves a problem that you perhaps shouldn't have.
#' @author J. Carroll, \email{}
#' @references \url{}
#' @param g ggplot graph with categorical x axis
#' @param pics ordered list of pictures to place along x-axis
#' @return NULL (called for the side-effect of producing a new grob with images for x-axis labels)
#' @import grid
#' @import ggplot2
#' @export
#' @example
#' \dontrun{ggplot(data, aes(x=factor(x),y=y)) + geom_point() %>% add_images_as_xlabels(pics)}
add_images_as_xlabels <- function(g, pics) {
## ensure that the input is a ggplot
if(!inherits(g, "ggplot")) stop("Requires a valid ggplot to attach images to.")
## extract the components of the ggplot
gb <- ggplot_build(gg)
xpos <- gb$panel$ranges[[1]]$x.major
yrng <- gb$panel$ranges[[1]]$y.range
## ensure that the number of pictures to use for labels
## matches the number of x categories
if(length(xpos) != length(pics)) stop("Detected a different number of pictures to x categories")
## create a new grob of the images aligned to the x-axis
## at the categorical x positions
my_g <-"grobTree", Map(rasterGrob, pics, x=xpos, y=0))
## annotate the original ggplot with the new grob
gg <- gg + annotation_custom(my_g,
xmin = -Inf,
xmax = Inf,
ymax = yrng[1] + 0.25*(yrng[2]-yrng[1])/npoints,
ymin = yrng[1] - 0.50*(yrng[2]-yrng[1])/npoints)
## turn off clipping to allow plotting outside of the plot area
gg2 <- ggplotGrob(gg)
gg2$layout$clip[gg2$layout$name=="panel"] <- "off"
## produce the final, combined grob

This comment has been minimized.

Copy link

@baptiste baptiste commented Jun 2, 2016

annotation_custom is really a hacky way of doing this; better post-process the gtable, or bypass the element_zzz checks with element_blank.


This comment has been minimized.

Copy link
Owner Author

@jonocarroll jonocarroll commented Jun 2, 2016

@baptiste you're 100% correct and your method is vastly superior/exactly what I was after. New gist: and blog post: (will be scraped to R-bloggers sometime today). Thank you very kindly for your help.

Any chance of a new push to get this into ggplot2 officially?


This comment has been minimized.

Copy link

@yeedle yeedle commented Mar 6, 2017

 gb   <- ggplot_build(gg)

that's a typo, should be ggplot_build(g)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment