3

I have a plot in ggplot and I wish to overlay a map legend that I have created with base R code. I do not know how to overlay base R graphics on top of a ggplot and would be grateful for assistance.

Currently I have a ggplot legend that looks like this: enter image description here

There are several things that I do not like about this legend that I would like to change (and that resulted in me thinking it would be easier to resort to base R graphics to do so).

In particular, I wish to eliminate the white space between the boxes in the legend and I wish to add tick marks between the boxes too. I also wish to put "5" beneath the first tick mark separating the first and second boxes; "10" beneath the tick mark separating the second and third boxes; and "20" beneath the tick mark separating the third and forth boxes. I also wish to make the boxes in the legend the same size as one of the "bins" in my plot (I use the stat_bin2d layer).

Relevant code:

ggplot()+
stat_bin2d(restaurants.df,binwidth=c(1500,2500), alpha=0.6,aes(x=X,y=Y,fill=cut(..count.., c(0,5,10,20,Inf))))+
scale_fill_manual("No. of Restaurants",labels=c("<5","5-10","10-20",">20"),values=cols, guide = guide_legend(direction = "horizontal", title.position = "top",                                      ticks=TRUE,label.position="bottom")) + 
theme(legend.background = element_rect(colour = "black"),
    legend.key = element_rect(color='black'))
ZAC
  • 97
  • 1
  • 6
  • 3
    I'm pretty sure one of the many ggplot experts around here could show you how to create your desired legend with ggplot. It's probably easier and more robust than trying to overlay the base R. – Molx Sep 14 '15 at 23:35
  • you will have a hard time, `ggplot2` uses `grid` graphics, see `?graphics` – Rorschach Sep 14 '15 at 23:50
  • 3
    You should probably look at the package gridBase. – joran Sep 15 '15 at 00:30
  • 1
    There are more than a few of us capable of pretty useful things with cartography and ggplot2. Give us more deets (i.e. code & data) so we can help! – hrbrmstr Sep 15 '15 at 00:49
  • Thank you for offering support - I have now updated my question so that I hope it will be clearer exactly what I am trying to achieve – ZAC Sep 15 '15 at 01:25
  • 2
    the detailed description of your legend makes it sound like a plot in itself. Which you could perhaps produce with ggplot, and include with `annotation_custom` – baptiste Sep 15 '15 at 01:28

2 Answers2

6

@baptiste's comment got me interested in trying to create a plot that would become the legend. Here's my attempt. I use geom_tile to create a plot that will become the legend. The OP didn't provide sample data so I've created a plot using the built-in mtcars data, just to have something to put the legend next to. Then I use grid.arrange to create the final plot-plus-legend layout.

library(ggplot2)
library(grid)
library(gridExtra) 

## Create legend

# Fake data
dat = data.frame(x=1:4, y="Group", col=factor(1:4))

# Create a plot that will become the legend
legend = ggplot(dat, aes(x,y, fill=col)) + 
  geom_tile(show.legend=FALSE) +
  scale_x_continuous(breaks=c(1.5,2.5,3.5), labels=c(5,10,20)) +
  scale_fill_manual(values=c("yellow","orange","red","darkred")) +
  labs(y="", x="") +
  ggtitle("No. of Restaurants") +
  theme_bw() +
  theme(panel.border=element_blank(),
        axis.ticks.y=element_blank(),
        axis.text.y=element_blank())

## Create a plot to put next to the legend
p1 = ggplot(mtcars, aes(mpg, wt)) + 
  geom_point() +
  theme(plot.margin=unit(c(0,0,0,0)))

# Arrange plot and legend
grid.arrange(p1, arrangeGrob(rectGrob(gp=gpar(col=NA)), 
                             legend,
                             rectGrob(gp=gpar(col=NA)),
                             heights=c(0.42,0.16,0.42)), 
             widths=c(0.8,0.2))

enter image description here

eipi10
  • 91,525
  • 24
  • 209
  • 285
3

It might turn out to be easier to define your own custom legend,

library(gridExtra)
library(grid)

stripGrob <- function(cols = c("yellow","orange","red","darkred"), 
                      labels= c(5,10,20), 
                      gp=gpar(fontsize=10,fontface="italic"), vp=NULL){
  n <- length(cols)
  rg <- rasterGrob(t(cols), y=1, vjust=1, interpolate = FALSE)
  sg <- segmentsGrob(x0=seq(1/n, 1-1/n, length.out=n-1),
                     x1=seq(1/n, 1-1/n, length.out=n-1),
                     y0=unit(1,"npc") - grobHeight(rg),
                     y1=unit(1,"npc") - grobHeight(rg) - unit(2,"mm"),
                     gp=gpar(lwd=2))
  tg <- textGrob(labels, x=seq(1/n, 1-1/n, length.out=n-1),
                 unit(1,"npc") - grobHeight(rg) - grobHeight(sg) - unit(1,"mm"), 
                 vjust=1)

  stripGrob <- gTree(children = gList(rg, tg, sg), gp=gp, vp=vp)
}

qplot(1,1) +
  annotation_custom(grob=stripGrob(), xmax=1.0)

enter image description here

baptiste
  • 75,767
  • 19
  • 198
  • 294