Created
June 2, 2016 12:10
-
-
Save jonocarroll/1d1bdb00a7b3910d62bf3eec8a77b4a7 to your computer and use it in GitHub Desktop.
Replace categorical x-axis labels with images
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#' 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{jono@@jcarroll.com.au} | |
#' @references \url{http://stackoverflow.com/questions/29939447/icons-as-x-axis-labels-in-r-ggplot2} | |
#' | |
#' @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 <- do.call("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 | |
grid.newpage() | |
grid.draw(gg2) | |
return(invisible(NULL)) | |
} |
@baptiste you're 100% correct and your method is vastly superior/exactly what I was after. New gist: https://gist.github.com/jonocarroll/2f9490f1f5e7c82ef8b791a4b91fc9ca and blog post: http://jcarroll.com.au/2016/06/03/images-as-x-axis-labels-updated/ (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?
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
annotation_custom is really a hacky way of doing this; better post-process the gtable, or bypass the element_zzz checks with element_blank. http://stackoverflow.com/questions/14070953/photo-alignment-with-graph-in-r/14078391
tidyverse/ggplot2#1240