Search code examples
rggplot2

How can I get fine control over the position of a ggplot legend, now that a numeric 'legend.position' argument is deprecated?


To maximise the space given to the data in a ggplot graph I want to stack the y-axis title (rotated horizontally for accessibility purposes) and the legend. This has been possible until now using legend.position. For example:

ggplot(iris, aes(Sepal.Length, Petal.Width, shape = Species, colour = Species)) +
  geom_point() +
  theme(axis.title.y = element_text(angle = 0, vjust = 0.9),
        legend.position = c(-0.15, 0.2))

Produces: ggplot graph with legend positioned directly below the y-axis title

But now I've started using ggplot 3.5.0 I'm getting the message "Warning: A numeric legend.position argument in theme() was deprecated in ggplot2 3.5.0."

So, I've been trying to produce a non-deprecated alternative to my code, using the latest official guidance on ggplot legends, but have not succeeded. For example:

ggplot(iris, aes(Sepal.Length, Petal.Width, shape = Species, colour = Species)) +
  geom_point() +
  theme(axis.title.y = element_text(angle = 0, vjust = 0.9),
        legend.position = "left", 
        legend.justification.left = "bottom")

Produces a graph where the legend is positioned below and to the left of the y-axis title, rather than directly below: ggplot graph with legend positioned below and to the left of the y-axis title, rather than directly below it


Solution

  • To achieve the "old" behavior set legend.position="inside" and use legend.position.inside to pass your numeric vector for the legend placement.

    The code below uses patchwork to compare the old and the new way:

    library(ggplot2)
    
    p1 <- ggplot(iris, aes(Sepal.Length, Petal.Width, shape = Species, colour = Species)) +
      geom_point() +
      theme(
        axis.title.y = element_text(angle = 0, vjust = 0.9),
        legend.position = c(-0.15, 0.2)
      )
    #> Warning: A numeric `legend.position` argument in `theme()` was deprecated in ggplot2
    #> 3.5.0.
    #> ℹ Please use the `legend.position.inside` argument of `theme()` instead.
    #> This warning is displayed once every 8 hours.
    #> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
    #> generated.
    
    
    p2 <- ggplot(iris, aes(Sepal.Length, Petal.Width, shape = Species, colour = Species)) +
      geom_point() +
      theme(
        axis.title.y = element_text(angle = 0, vjust = 0.9),
        legend.position = "inside",
        legend.position.inside = c(-0.15, 0.2)
      )
    
    library(patchwork)
    
    p1 / p2