I've recently gotten frustrated by the same issue as reported here regarding the hacks required to make up for ggplot not adding NA fills to the legend (please if anyone knows an update to this, do tell).
I therefore created a similar hack, but in a fairly complex plot where I was trying to demonstrate several things at once. The plot required setting the size of points to a small value so therefore I needed override.aes
to have points large enough in the legend. Since I was using alpha
as well as colour
, I introduced both into the same legend key.
However, bizarrely (at least to me), the aes
override creates ugly whitespace between the legend key box margin and the fill, as shown in the map with and without the size aes override:
How does this happen, and how can I make it go away? Any help would be much appreciated.
Here's the code to reproduce this. As said, my true plot is more complex than this but this shows the general idea.
## create an example using the world data
require(rworldmap)
require(rgeos)
require(ggplot2)
require(viridis)
## Load world map and subset
world <- getMap()
world <- world[!world@data$ADMIN %in% c("French Southern and Antarctic Lands",
"Heard Island and McDonald Islands",
"French Guiana"),] #NA entries for these in REGION col
world <- world[world@data$REGION == "South America",]
world@data$id = rownames(world@data)
## create example where we have NA for the fill variable
world@data$fillvar <- world@data$LAT
world@data$fillvar[round(world@data$LAT) == -9] <- NA #Peru
## create spatial data frame for plotting
polydf = ggplot2::fortify(world, region="id")
polydf <- merge(polydf, world@data, by="id")
## create arbitrary grouping variable
polydf$groupvar <- ifelse(polydf$NAME == "Bolivia", "Bolivia", "NotBolivia") # the two main classes
# simulate hack where we name the NA fill case as a new grouping level (which we will use alpha for)
polydf$groupvar[is.na(polydf$fillvar)] <- 'Removed'
polydf$groupvar <- factor(polydf$groupvar)
## create centroid points to show the grouping with points, again manual hack for NA
pointsdf <- gCentroid(world[!is.na(world@data$fillvar),],byid=TRUE)
pointsdf <- as.data.frame(pointsdf@coords)
pointsdf$groupvar <- ifelse(rownames(pointsdf)=="Bolivia","Bolivia","NotBolivia")
pointsNA <- gCentroid(world[is.na(world@data$fillvar),], byid=TRUE)
pointsNA <- as.data.frame(pointsNA@coords)
pointsNA$groupvar <- "Removed"
pointsdf <- rbind(pointsdf, pointsNA)
pointsdf$groupvar <- factor(pointsdf$groupvar)
## plot with override.aes for size
sizeover <- ggplot(polydf) + theme_bw() +
aes(long,lat,group=group) +
geom_polygon(aes(fill=fillvar, alpha=groupvar)) + # shading also for groupvar
geom_path(color="black") +
coord_equal() +
scale_fill_viridis("Fill", na.value="black") +
geom_point(inherit.aes=FALSE, data=pointsdf, aes(x=x, y=y, group=groupvar, col=groupvar), size=1) +
scale_color_manual('Alpha + colour', values=c("black","transparent","white")) +
scale_alpha_manual('Alpha + colour', values=c(0.8,0.8, 1)) +
theme(legend.key = element_rect(colour = "black"), legend.box = "vertical", legend.position = "top") +
guides(color=guide_legend(override.aes = list(size=2)),
alpha=guide_legend(override.aes = list(alpha=c(1,1,1), fill=c('white','white','black'))))
## plot without override.aes for size
nosizeover <- ggplot(polydf) + theme_bw() +
aes(long,lat,group=group) +
geom_polygon(aes(fill=fillvar, alpha=groupvar)) + # shading also for groupvar
geom_path(color="black") +
coord_equal() +
scale_fill_viridis("Fill", na.value="black") +
geom_point(inherit.aes=FALSE, data=pointsdf, aes(x=x, y=y, group=groupvar, col=groupvar), size=1) +
scale_color_manual('Alpha + colour', values=c("black","transparent","white")) +
scale_alpha_manual('Alpha + colour', values=c(0.8,0.8, 1)) +
theme(legend.key = element_rect(colour = "black"), legend.box = "vertical", legend.position = "top") +
guides(alpha=guide_legend(override.aes = list(alpha=c(1,1,1), fill=c('white','white','black'))))
grid.arrange(sizeover, nosizeover, ncol=2)
The problem exists in both figures (sizeover
and nosizeover
), it's just more pronounced in the former. The guilty party is the function draw_key_polygon()
in ggplot2. It creates some space around the rectangle it draws, in proportion to the size
setting (see here). I'm not quite sure why it's written like that, but presumably there's a reason.
The simplest solution is similar to this answer to a different question. Replace the legend-drawing function for geom_polygon()
. In the case here, we don't even have to write a new one ourselves, we can just use an existing one:
GeomPolygon$draw_key <- ggplot2::draw_key_rect
sizeover
The only problem that this has created is that now the legend outline appears a bit thin, because the filled rectangle is drawn on top of the outline. We can fix this by making the line a bit thicker, by adding this to the plot:
+ theme(legend.key = element_rect(colour = "black", size = 1))
This seems like a reasonable solution to me.
Note that geom_polygon()
will continue using the modified legend drawing function for the remainder of your session. To undo, run:
GeomPolygon$draw_key <- ggplot2::draw_key_polygon