Placing legend above main title

2020-04-08 14:40发布

Placing the legend above the main title in ggplot2 when using theme(legend.position = "top") seemed to be the default (and unwanted) outcome in previous versions of ggplot: ggplot legend at top but below title?

In the current version of ggplot2, the legend places itself between the plot and the main title when setting theme(legend.position = "top"). A small example:

d <- data.frame(x = 1:2, y = 1:2, z = c("a", "b")) 
ggplot(d, aes(x = x, y = y, fill = z)) + 
  geom_col() +
  ggtitle("My title") +
  theme(legend.position = "top") 

enter image description here

How can I place the legend above main title?

标签: r ggplot2 legend
3条回答
男人必须洒脱
2楼-- · 2020-04-08 14:47

Or we can create a fake facet and put the plot title in it. After that do some tweaking to remove the strip facet and reduce the legend margin

library(ggplot2)

d <- data.frame(x = 1:2, y = 1:2, z = c("a", "b")) 
d$Title <- "My title\n"

# default legend key text
p1 <- ggplot(d, aes(x = x, y = y, fill = z)) + 
  geom_col() +
  facet_grid(~ Title) +
  theme(strip.text.x = element_text(hjust = 0, vjust = 1,
                                    size = 14, face = 'bold'),
        strip.background = element_blank()) +
  theme(legend.margin = margin(5, 0, 0, 0),
        legend.box.margin = margin(0, 0, -10, 0)) +
  theme(legend.position = "top") +
  NULL

# legend key text at the bottom
p2 <- ggplot(d, aes(x = x, y = y, fill = z)) + 
  geom_col() +
  facet_grid(~ Title) +
  theme(strip.text.x = element_text(hjust = 0, vjust = 1,
                                    size = 14, face = 'bold'),
        strip.background = element_blank()) +
  theme(legend.margin = margin(5, 0, 0, 0),
        legend.box.margin = margin(0, 0, -10, 0)) +
  guides(fill = guide_legend(label.position = "bottom",
                             title.position = "left", title.vjust = 1)) +
  theme(legend.position = "top") +
  NULL


library(patchwork)
p1 | p2

Created on 2018-10-12 by the reprex package (v0.2.1.9000)

查看更多
叼着烟拽天下
3楼-- · 2020-04-08 14:49

This requires a little more work than adjusting margins, but it should allow for more control over placement and sizing. I'm using functions from cowplot: get_legend to extract the legend from the plot, and plot_grid to create a grid of these two ggplot elements.

After creating the plot p with a legend, cowplot::get_legend(p) then creates a ggplot object that is just the legend. Reposition them with plot_grid while adding a theme call that removes the legend from p. You'll probably want to tweak the heights and perhaps adjust margins.

library(ggplot2)

p <- ggplot(d, aes(x = x, y = y, fill = z)) + 
  geom_col() +
  ggtitle("My title") +
  theme(legend.position = "bottom") 

legend <- cowplot::get_legend(p)

cowplot::plot_grid(
  legend,
  p + theme(legend.position = "none"),
  ncol = 1, rel_heights = c(0.1, 1)
)

Created on 2018-10-12 by the reprex package (v0.2.1)

查看更多
beautiful°
4楼-- · 2020-04-08 14:56
library(ggplot2)

ggplot(mtcars, aes(wt, mpg, color=cyl)) +
  geom_point() +
  labs(title = "Hey") +
  theme(plot.margin = margin(t=4,1,1,1, "lines")) +
  theme(legend.direction = "horizontal") +
  theme(legend.position = c(0.5, 1.2))

enter image description here

There are other ways as well, but this was the easiest one that came to mind.

查看更多
登录 后发表回答