2

I am plotting a scatterplot in ggplot with icons and I am stuck with producing a legend using the icons.

THere is a function in the ggimage documentation called "draw_key_image" but I don't really understand how to use it or the required arguments.

The documentation says "data = A single row data frame containing the scaled aesthetics to display in this key" but this does not help me at all!

https://www.rdocumentation.org/packages/ggimage/versions/0.2.7/topics/draw_key

##Hopefully reproducible code with example data

##Icons downloaded from https://labs.mapbox.com/maki-icons/
library(ggplot2)
library(ggimage)
library(rsvg)

Activity<-"Walk"
x = -2
y = 2.5
icon<-".\\mapbox-maki-a6d16d4\\icons\\shoe-15.svg"
test_data<-data.frame( Activity, x, y, icon)

p_test<-ggplot(data = test_data,
          aes(x = x, 
              y = y))+
  geom_image(aes(image=icon), size=.03)
  p_test

Please could someone help me add a legend with the icon and label of "Walk"?

Many thanks, Jo

tjebo
  • 21,977
  • 7
  • 58
  • 94
Jo_G
  • 23
  • 3
  • check this thread https://stackoverflow.com/questions/36133374/custom-legend-with-imported-images. and https://stackoverflow.com/questions/27637455/display-custom-image-as-geom-point – tjebo Apr 20 '20 at 21:31

1 Answers1

4

This draw_key function is something that is supposed to work 'under the hood'. See documentation

Each geom has an associated function that draws the key when the geom needs to be displayed in a legend. These functions are called draw_key_*(), where * stands for the name of the respective key glyph. The key glyphs can be customized for individual geoms by providing a geom with the key_glyph argument (see layer() or examples below.)

I dare say, ggimage may possibly deserve some more development in this regard.

https://github.com/GuangchuangYu/ggimage/issues/18 shows that currently only three types of legend glyphs are supported, and you activate them with changing the options (see code below). One can also change the underlying draw_key function and instead of loading the R image, you can load your image. It needs to be a png though, so first you need to convert it to png.

You can find the source code which I modified here

The disadvantage is that it currently only accepts one image. In order to map several images to an aesthetic of your geom, you could find inspiration in grandmaster Baptiste's creation of a 'minimalist' geom. https://stackoverflow.com/a/36172385/7941188

library(ggplot2)
library(ggimage)

Activity<-c("Walk1", "Walk2")
x = 1:2
y = 2:3

icon<-"https://raw.githubusercontent.com/mapbox/maki/a6d16d49a967b73d9379890a7b26712b12b8daef/icons/shoe-15.svg"
bitmap <- rsvg::rsvg(icon, height = 50)

png::writePNG(bitmap, "shoe.png", dpi = 144)

test_data<-data.frame( Activity, x, y, icon)

options(ggimage.keytype = "image")

ggplot(data = test_data, aes(x = x, y = y)) +
  geom_image(aes(image=icon, color = Activity), size=.03)

The icon changed to the R logo:

Now let's modify the draw_key_image function. You also need to call it with the key_glyph argument in geom_image.


draw_key_image <- function (data, params, size) {
  kt <- getOption("ggimage.keytype")
if (kt == "image") {
    img <- magick::image_read("shoe.png")
    grobs <- lapply(seq_along(data$colour), function(i) {
      img <- ggimage:::color_image(img, data$colour[i], data$alpha[i])
      grid::rasterGrob(0.5, 0.5, image = img, width = 1, height = 1)
    })
    class(grobs) <- "gList"
    keyGrob <- ggplot2:::ggname("image_key", grid::gTree(children = grobs))
  }
  return(keyGrob)
}

ggplot(data = test_data, aes(x = x, y = y)) +
  geom_image(aes(image=icon, color = Activity), size=.03, 
             key_glyph = draw_key_image) # you need to add this argument

Created on 2020-04-20 by the reprex package (v0.3.0)

helpful threads: convert svg to png

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • How to change the code so that the legend will have a different image for each element ? – yuliaUU Apr 23 '20 at 06:35
  • @yuliaUU see the thread to which I linked. here to your convenience again: https://stackoverflow.com/a/36172385/7941188 This basically requires a new geom. – tjebo Apr 23 '20 at 09:11
  • sorry, I am not sure what I should modify to add an image in that code – yuliaUU Apr 23 '20 at 17:46
  • also, linked code does not work and throw error :Error: ScaleDiscreteIdentity was built with an incompatible version of ggproto. Please reinstall the package that provides this extension.: – yuliaUU Apr 23 '20 at 17:54
  • @yuliaUU if the provided links do not help you, I'd suggest you to ask a new question! may be worth it – tjebo Apr 23 '20 at 17:57
  • i did here: https://stackoverflow.com/questions/61381710/is-it-possible-to-add-custom-shapes-from-png-to-ggplot-legend?noredirect=1#comment108594633_61381710 – yuliaUU Apr 23 '20 at 18:16
  • @yuliaUU it would help people if you would link to this question and answer here so they don't need to reinvent the wheel again. – tjebo Apr 23 '20 at 18:20
  • 1
    but this question is slightly different: they use same image with different color,but my question is different: I want different image for different color. I rephrased my question a bit and cited this question in my explanation. thanks – yuliaUU Apr 23 '20 at 18:43
  • Thank you, @Tjebo, your code worked for me (sorry for delayed reply!). Also, I found it really helpful as your code allowed me to improve the image quality of my icons which was previously pretty low. – Jo_G May 12 '20 at 09:23
  • Also, I voted on your answer but I don't count I'm afraid.... – Jo_G May 12 '20 at 09:26