How to selectively add a box around the legend key

How can I add a margin around the legend just for color not for size while keeping both legend keys. The code below adds fields to both mappings.

x<-1:6;
y<-factor(2:7);
z<-1:6;
df <- data.frame(x,y,z)

ggplot(df, aes(x,y)) + 
    geom_point(aes(colour=y, size = z) )   +
    theme(legend.key = element_rect(colour = '#bdbdbd', size = 0.6))

      

enter image description here

+3


source to share


1 answer


Here is one approach using layout ggplot

and gtable

. It fetches the color legend from the layout, draws rectangles around each key, re-strips the legend, and then inserts the legend back into the ggplot layout.

library(ggplot2)
library(gtable)
library(grid)

x<-1:6;
y<-factor(2:7);
z<-1:6;
df <- data.frame(x,y,z)

p = ggplot(df, aes(x,y)) + 
    geom_point(aes(colour=y, size = z) )   

# get ggplot grob
gt = ggplotGrob(p)

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

# The legend has two parts.
# Get the second part - the color legend
leg2 = leg$grobs[[1]]$grobs[[2]]

# Get the locations of the top of each box containing the legend keys
# in this legend layout
rects <- leg2$layout$t[grepl("bg", leg2$layout$name)]

# Draw boxes around each key
for(i in rects) leg2 = gtable_add_grob(leg2, grid.rect(gp = gpar(col = '#bdbdbd', fill = NA)), t = i, l = 2)


# Insert new color legend back into the combined legend   
leg$grobs[[1]]$grobs[2][[1]] <- leg2

# 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



Here is a second approach (based on @Baptiste here) that draws two plots , one containing a size legend and the other a color legend (from the box around the keys). It then extracts the legends from each plot layout, merges the two legends into one legend, then inserts the merged legend back into one of the layouts.

library(ggplot2)
library(gtable)
library(grid)

x<-1:6;
y<-factor(2:7);
z<-1:6;
df <- data.frame(x,y,z)

p1 = ggplot(df, aes(x,y)) + 
    geom_point(aes(colour=y, size = z) ) +
    scale_colour_discrete(guide = "none")

p2 = ggplot(df, aes(x,y)) + 
    geom_point(aes(colour=y, size = z) ) +
    scale_size(guide = "none")   +
theme(legend.key = element_rect(colour = '#bdbdbd', size = 0.6))

# Get ggplot grobs
gt1 = ggplotGrob(p1)
gt2 = ggplotGrob(p2)

# Get the legends
leg1 = gtable_filter(gt1, "guide-box")
leg2 = gtable_filter(gt2, "guide-box")

# Combine the legends
leg <- rbind(leg1[["grobs"]][[1]],  leg2[["grobs"]][[1]], size = "first")

# Insert legend into g1 (or g2)
gt1$grobs[gt1$layout$name == "guide-box"][[1]] <- leg

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

      

enter image description here

+1


source







All Articles