A good friend of mine recently finished her PhD in Geography, and I wanted to make her some sort of signature gift to commemorate her tremendous achievement. Since she studies human-wildlife conflict in the Serengeti, I thought it would be cool to plot some of her data in the shapes of the animals they represented. This turned out to be easier than I thought it would be, and I wanted to share how it went down.

Creating a custom font

This was the most time-intensive part, because I had to find Creative Commons-Licensed images to use for all the animals. Luckily, Google Images has a search input for this, which helped.

Her animals were: bushpig, crocodile, baboon, elephant, leopard, lion, hyena, and porcupine. So I knew I would end up with a font of 9 characters. For better definition of the shapes, I wanted to use silhouettes - so for a few cases, I had to download and edit the alpha, fill, and size of the images in PowerPoint or Preview. The final image set looked like this:

bushpig crocodile baboon elephant leopard lion hyena porcupine

Pretty cool, right? Now to turn them in to a font! I did this with fontastic.me. Their website is extremely easy to use, and I haven’t received a single item of spam mail from them since, which I appreciate.

I named the font “serengeti” and published it (you can download it here if you want to use it yourself!). Fontastic makes it very easy to download the serengeti.ttf file, which I then installed on my computer. Installing fonts is pretty simple on a Mac - I’m not sure what’s involved with a PC, sorry!

Bringing the new font in to R

The first step is to install and load the package extrafont. You can find more info on that here. If you want to use non-standard fonts in documents as well as plots, definitely read the part about embedding fonts into PDFs.

Once your computer’s fonts are registered with R (using font_import(), which, be warned, is a 5-10 minute process), you will be able to use all the fonts you have installed in any figure you make by running the function loadfonts().

Making the figure

The figure I wanted to make was a plot of human-wildlife conflict, by animal and season - this meant that the number of incidents would be plotted on the y-axis, and the season (rainy, dry, etc) would be on the x-axis.

Please note that for this example, I’ve randomized my friend’s original data - the plot below should NOT be taken as representative of real human-wildlife conflict incident reports.

geom_text(), not geom_point()

The key to getting the plot to display each animal symbol was to map the label argument of geom_text() to the keyboard key that the animal’s font symbol was assigned (so “e” for elephant, “h” for hyena, etc). I also had to build it up in different data layers (one layer for each animal). The code is below, along with intermittent figure previews.

# split master dataframe (d2) into one dataframe for each animal:
dfs <- split(d2, with(d2, list(d2$Animal)), drop = TRUE)
dfs <- dfs[-1] # remove one empty df
# attach the dataframes to the global environment so I can call them easily by animal name:
list2env(dfs,envir=.GlobalEnv)
## <environment: R_GlobalEnv>
p <- ggplot(Elephant, aes(x = Season, y = count)) + geom_text(label = "e", family = "serengeti", size =10, color = "#393C25") 
p

p <- p + geom_text(data = Hyena, label = "h", family = "serengeti", size = 4,
                   color = "#CA590F")
p

p <- p + geom_text(data = Hippopotamus, label = "i", family = "serengeti", size = 8,
                   color = "#452139", position = position_nudge(y = 0.4, x = -.05))
p


A note on colors - I knew I wanted to use Serengeti-flavored palette for the plot; I chose the individual hex colors by searching colorhunter.com.

Now that you’re getting a sense of how the plot is layering up, we can plot the rest of the figure in one chunk:

p <- p + geom_text(data = Leopard, label = "k", family = "serengeti", size = 6,
                   color = "#891300", position = position_nudge(x = 0.05))

p <- p + geom_text(data = Lion, label = "l", family = "serengeti", size = 6,
                   color = "#FFBA04", position = position_nudge(x = -0.05))

p <- p + geom_text(data = Porcupine, label = "p", family = "serengeti", size = 5,
                   color = "#3364C9", position = position_nudge(y = 0.5))

p <- p + geom_text(data = Baboon, label = "b", family = "serengeti", size = 4,
                   color = "#5E2F18", position = position_nudge(x = 0.05))

p <- p + geom_text(data = Bushpig, label = "!", family = "serengeti", size = 6,
                   color = "#007EC2")

p <- p + geom_text(data = Crocodile, label = "c", family = "serengeti", size = 6,
                   color = "#547137" )


p <- p + theme(legend.position = "none",
               text = element_text(size = 12)) + ylim(c(0, 10)) + scale_x_discrete(labels = c("Dry Season",  "Early Rainy Season", "Late Rainy Season", "Transition", "Unknown")) + 
  labs(x = NULL, y = "rnorm(length(d2), mean = 5, sd = 2)") 

p <- p + theme(plot.margin = unit(c(10,30, 10, 5) ,"points"))

p


And that’s it! With a little more tweaking and personalization, the final figure turned out great, and I made it into a gift for my friend by uploading the image to my artist page on Society6.

Shameless plug: if you want to flaunt your love for R and support a good cause at the same time, take a look at the Davis R-Users Group’s Society6 page! We’ve crowd-sourced our dissertation data, and sales from the page will go toward a Data Carpentry fund to hold workshops in under-funded/underrepresented regions.