Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple legends with position="inside" #5712

Open
MauricioCely opened this issue Feb 26, 2024 · 8 comments · May be fixed by #6210
Open

Multiple legends with position="inside" #5712

MauricioCely opened this issue Feb 26, 2024 · 8 comments · May be fixed by #6210

Comments

@MauricioCely
Copy link

I have recently installed the ggplot2 3.5.0 release, and after reading the new features added to the Legends Placement, I was very curious to know if it is possible to have multiple inside legends (position = "inside") at different positions by using the new legend.position.inside argument for each guide. For example, cty legend at bottom-right and cyl at top-right. However, it does not work.

library(ggplot2) # Create Elegant Data Visualisations Using the Grammar of Graphics CRAN v3.5.0

ggplot(mpg, aes(displ, hwy, shape = drv, colour = cty, size = year)) +
  geom_point(aes(alpha = cyl)) +
  guides(
    colour = guide_colourbar(position = "inside",
                             theme = theme(legend.position.inside = c(1, 0))),
    size   = guide_legend(position = "top"),
    alpha  = guide_legend(position = "inside", 
                          theme = theme(legend.position.inside = c(0, 1))),
    shape  = guide_legend(position = "left")
  )

image

It seems only works by using the global theme’s legend.position.inside arguments, grouping both legends at the same position, but for now is not possible to not place them separately.

@thomasp85
Copy link
Member

This is not possible at this time

@teunbrand
Copy link
Collaborator

Should this be possible? I cannot think of a compelling use case on top of my head, or at least, more compelling than satisfying curiosity.

@MauricioCely
Copy link
Author

Some time ago, I saw this issue in Stackoverflow:

https://stackoverflow.com/questions/21798364/independently-move-2-legends-ggplot2-on-a-map

@botanize
Copy link
Contributor

botanize commented May 3, 2024

I'm running into this as well. The documentation doesn't say anything about which components of theme are respected in guide_legend, at the moment there's no warning or error, the plot just doesn't respect the API as documented.

@twest820
Copy link

I seem to be hitting either a related issue or another manifestation of this, though the use case is a bit different as it's a single legend per figure with multiple figures patchworked together. The deprecation warning tells you to use legend.position.inside but changing from legend.position to legend.position.inside results in legends being shown outside the figures unless guide_legend(position = "inside") is also specified. While the OP's question isn't supported it's unclear what interactions with the global theme are currently supported.

It's easy to read the the blog post as saying this isn't expected behavior: "To cover such cases, there is now a specialised legend.position.inside argument that controls the positioning of legends with position = "inside" regardless of whether the position was specified in the theme or in the guide." but it's not entirely clear to which of position and legend.position.inside it's referring to.

@teunbrand
Copy link
Collaborator

teunbrand commented May 31, 2024

I understand the confusion this may have caused and it should be made clearer in the documentation which theme elements are used in the legend itself versus which ones are used to compose the legend within the plot.

With regards to positions;
The position argument of the guide function determines in which area of the plot it is displayed.
In absence of such argument, the global theme(legend.position) argument is used.
It never uses the local theme for this, as it has an argument that serves this function.
The theme(legend.position.inside) argument determines where legends with position = "inside" (directly or by defaulting through the global theme) are placed in the plot panel.

With regards to which theme elements guides respond to;
As a rule of thumb, these are the elements that only affect a single guide.
Not elements that rule how guides are positioned in the guide box (e.g. legend.justification, legend.location, legend.box, legend.box.just and legend.box.spacing, legend.position and legend.position.inside, legend.spacing). To get an exact overview of which elements are taken from the theme, you can inspect a guide's elements field:

ggplot2::guide_legend()$elements
#> $background
#> [1] "legend.background"
#> 
#> $margin
#> [1] "legend.margin"
#> 
#> $key
#> [1] "legend.key"
#> 
#> $key_height
#> [1] "legend.key.height"
#> 
#> $key_width
#> [1] "legend.key.width"
#> 
#> $text
#> [1] "legend.text"
#> 
#> $theme.title
#> [1] "legend.title"
#> 
#> $spacing_x
#> [1] "legend.key.spacing.x"
#> 
#> $spacing_y
#> [1] "legend.key.spacing.y"
#> 
#> $text_position
#> [1] "legend.text.position"
#> 
#> $title_position
#> [1] "legend.title.position"
#> 
#> $byrow
#> [1] "legend.byrow"

Created on 2024-05-31 with reprex v2.1.0

@neellab-umd
Copy link

I am running into this issue as well. I have two legends I want to place inside my map and I want to control where I put each of them separately so they plot around the actual contents of the map. But it seems I can only control the location inside the plot for one legend separately with guides() or all legends together in theme(). The only workarounds seem to be creating the legends as separate objects and then plotting them together with the original ggplot with cowplot. Seems like a very inefficient way to do this. Is it really the only way?

@teunbrand
Copy link
Collaborator

Currently, that is the only way I imagine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants