Konrad
Konrad

Reputation: 18657

Common border across two legends in ggplot2

I'm generating a simple chart:

data(iris); require(ggthemes)
ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) +
  geom_point(aes(shape=Species, colour=Petal.Width)) + 
  scale_colour_gradient() +
  theme_gdocs() +
  labs(shape="Species label", colour="Petal width label")

Initial chart

I would like to draw a common border across those two legends:

with common border

Obviously the code theme(legend.background = element_rect(colour = 'black')) will generate two borders, each for each legend element.

Upvotes: 3

Views: 904

Answers (1)

Sandy Muspratt
Sandy Muspratt

Reputation: 32874

Edit
As of version 2.2.0, ggplot allows a border for each individual legend (legend.background), and a border for the combined legend (legend.box.background). Set the legend.box.background to desired colors, fills, sizes, etc. But also set legend.background to element_blank().

ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) +
  geom_point(aes(shape=Species, colour=Petal.Width)) + 
  scale_colour_gradient() +
  theme_gdocs() +
  labs(shape="Species label", colour="Petal width label") +

   theme(legend.background = element_blank(),
         legend.box.background = element_rect(size = 2))

You probably need to delve into the structure of the ggplot grob; something like this:

Minor edit: Updating to ggplot2 2.0.0 (and ggthemes 3.0.0)

# Load packages and data
library(ggplot2)
library(gtable)
library(grid)

data(iris)

# Small problem with theme_gdocs drawing a border around each legend.
# Fixed in the github development version
    # library(devtools)
    # install_github("jrnold/ggthemes")
library(ggthemes)


p <- ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) +
  geom_point(aes(shape=Species, colour=Petal.Width)) + 
  scale_colour_gradient() +
  theme_gdocs() +
  labs(shape="Species label", colour="Petal width label")

# Get the ggplot grob
gt = ggplotGrob(p)

# Get the combined legend
leg = gtable_filter(gt, "guide-box")

# Get the individual legends - to get their widths and heights
leg1 = leg$grobs[[1]]$grobs[[1]]
leg2 = leg$grobs[[1]]$grobs[[2]]

# Calculate widths and heights for border (Note: some margin widths are dropped from widths)
rectHeight = sum(leg1$heights + leg2$heights)
rectWidth = sum(unit.pmax(leg1$widths[3:5], leg2$widths[3:5]))

# Create border with widths and heights 
rect <- rectGrob( width = rectWidth, height = rectHeight,
        gp = gpar(col = "black", fill = NA, lwd = 5), name = "gRect")

# Create combined legend - i.e., legend plus border
leg <- grobTree(leg, rect)

# Insert combined legend back into ggplot grob
gt$grobs[gt$layout$name == "guide-box"][[1]] <- leg

# Draw it
grid.newpage()
grid.draw(gt)

enter image description here

Upvotes: 2

Related Questions