如何在ggplot中独立定位两个图例
标题很好涵盖它。
我有两个关于尺寸和颜色的传说,希望在图的上面和上面有一个。
这是可能的,如果是的话,如何
TIA
根据我的理解,基本上ggplot2
传说控制非常有限。 这是哈德利书(第111页)的一段:
ggplot2试图使用尽可能less的图例来准确传达剧情中使用的美学。 如果一个variables与多个审美一起使用,它通过结合传奇来实现这一点。 图6.14给出了点geom的一个例子:如果颜色和形状都映射到相同的variables,那么只需要一个图例。 为了合并传说,它们必须具有相同的名称(相同的图例标题)。 因此,如果您更改其中一个合并图例的名称,则需要更改所有这些图例的名称。
可以通过从地块中提取不同的传说,然后在相关地块中安排传说来完成。 这里的代码使用gtable
包中的函数进行提取,然后使用gridExtra
包中的函数进行排列。 目的是要有一个包含彩色图例和大小图例的图。 首先,从仅包含彩色图例的图中提取彩色图例。 其次,从仅包含大小图例的图中提取大小图例。 第三,绘制一个不包含传说的情节。 第四,把情节和两个传说合并成一个新的情节。
# Some data df <- data.frame( x = 1:10, y = 1:10, colour = factor(sample(1:3, 10, replace = TRUE)), size = factor(sample(1:3, 10, replace = TRUE))) library(ggplot2) library(gridExtra) library(gtable) library(grid) ### Step 1 # Draw a plot with the colour legend (p1 <- ggplot(data = df, aes(x=x, y=y)) + geom_point(aes(colour = colour)) + theme_bw() + theme(legend.position = "top")) # Extract the colour legend - leg1 leg1 <- gtable_filter(ggplot_gtable(ggplot_build(p1)), "guide-box") ### Step 2 # Draw a plot with the size legend (p2 <- ggplot(data = df, aes(x=x, y=y)) + geom_point(aes(size = size)) + theme_bw()) # Extract the size legend - leg2 leg2 <- gtable_filter(ggplot_gtable(ggplot_build(p2)), "guide-box") # Step 3 # Draw a plot with no legends - plot (plot <- ggplot(data = df, aes(x=x, y=y)) + geom_point(aes(size = size, colour = colour)) + theme_bw() + theme(legend.position = "none")) ### Step 4 # Arrange the three components (plot, leg1, leg2) # The two legends are positioned outside the plot: # one at the top and the other to the side. plotNew <- arrangeGrob(leg1, plot, heights = unit.c(leg1$height, unit(1, "npc") - leg1$height), ncol = 1) plotNew <- arrangeGrob(plotNew, leg2, widths = unit.c(unit(1, "npc") - leg2$width, leg2$width), nrow = 1) grid.newpage() grid.draw(plotNew) # OR, arrange one legend at the top and the other inside the plot. plotNew <- plot + annotation_custom(grob = leg2, xmin = 7, xmax = 10, ymin = 0, ymax = 4) plotNew <- arrangeGrob(leg1, plotNew, heights = unit.c(leg1$height, unit(1, "npc") - leg1$height), ncol = 1) grid.newpage() grid.draw(plotNew)
这是使用ggplot2
和cowplot
(= ggplot2扩展)包的另一个解决scheme。
该方法与Sandys类似,因为它将图例作为独立对象取出,并让您独立进行布局。 它主要是为属于两个或更多地块的多个地块的多个传说devise的。
从这个答案中得到了使用的函数g_legend
。
这个想法如下:
- 创buildPlot1,Plot2,…,PlotX 无图例
- 使用图例创buildPlot1,Plot2,…,PlotX
- 将步骤2中的图例提取到单独的对象中
- 设置传奇网格,按照自己想要的方式排列传奇
- 创build网格结合阴谋和传说
它似乎有点复杂,时间/代码comsuming,但build立一次,你可以适应和使用它的每一种情节/传奇定制。
library(ggplot2) library(cowplot) # set up function g_legend<-function(a.gplot){ tmp <- ggplot_gtable(ggplot_build(a.gplot)) leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") legend <- tmp$grobs[[leg]] return(legend) } # Some data df <- data.frame( Name = factor(rep(c("A", "B", "C"), 12)), Month = factor(rep(1:12, each=3)), Temp = sample(0:40, 12), Precip = sample(50:400, 12)) # create plot1 plot1 <- ggplot(df, aes(Month, Temp, fill = Name)) + geom_point(show.legend = F, aes(group = Name, colour = Name), size = 3, shape = 17) + geom_smooth(method = "loess", se = F, aes(group = Name, colour = Name), show.legend = F, size = 0.5, linetype = "dashed") # create plot2 plot2 <- ggplot(df, aes(Month, Precip, fill = Name)) + geom_bar(stat = "identity", position = "dodge", show.legend = F) + geom_smooth(method = "loess", se = F, aes(group = Name, colour = Name), show.legend = F, size = 1, linetype = "dashed") + scale_fill_grey() # create legend1 legend1 <- ggplot(df, aes(Month, Temp)) + geom_point(show.legend = T, aes(group = Name, colour = Name), size = 3, shape = 17) + geom_smooth(method = "loess", se = F,aes(group = Name, colour = Name), show.legend = T, size = 0.5, linetype = "dashed") + labs(colour = "Station") + theme(legend.text=element_text(size=8), legend.title = element_text(face = "italic", angle = -0, size = 10)) # create legend2 legend2 <- ggplot(df, aes(Month, Precip, fill = Name)) + geom_bar(stat = "identity", position = "dodge", show.legend = T) + scale_fill_grey() + guides(fill = guide_legend(title = "", title.theme = element_text(face = "italic", angle = -0, size = 10))) + theme(legend.text=element_text(size=8)) # extract "legends only" from ggplot object legend1 <- g_legend(legend1) legend2 <- g_legend(legend2) # setup legends grid legend1_grid <- cowplot::plot_grid(legend1, align = "v", nrow = 2) # add second legend to grid, specifying its location legends <- legend1_grid + ggplot2::annotation_custom(grob = legend2, xmin = 0.5, xmax = 0.5, ymin = 0.55, ymax = 0.55) # plot "plots" + "legends" (with legends in between plots) cowplot::plot_grid(plot1, legends, plot2, ncol = 3, rel_widths = c(0.45, 0.1, 0.45))
例子:
更改最后一个plot_grid()
调用的顺序将传说向右移动:
cowplot::plot_grid(plot1, plot2, legends, ncol = 3, rel_widths = c(0.45, 0.45, 0.1))
Example2 160wpb4.png