如何在图例键周围有选择地添加框

How to selectively add box around legend key

我怎样才能在图例键周围添加框,只针对颜色而不是尺寸,同时保留两个图例键。下面的代码将框添加到两个映射。

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))

这是一种使用 ggplot 布局和 gtable 的方法。它从布局中提取颜色图例,在每个键周围绘制框,重新组合图例,然后将图例重新插入到 ggplot 布局中。

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's 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)

这是绘制两个图的第二种方法(基于@Baptiste 的 answer here):一个包含尺寸图例,另一个包含颜色图例(键周围有框)。然后从每个图的布局中提取图例,将两个图例组合成一个图例,然后将组合的图例插入到其中一个布局中。

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)