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

Legend title is incorrectly aligned when horizontal #2465

Open
hadley opened this issue Feb 27, 2018 · 12 comments
Open

Legend title is incorrectly aligned when horizontal #2465

hadley opened this issue Feb 27, 2018 · 12 comments

Comments

@hadley
Copy link
Member

@hadley hadley commented Feb 27, 2018

library(ggplot2)

df <- data.frame(z = 1:5)
p <- ggplot(df, aes(1, 1, colour = z)) + geom_point()

# Title should be centered with legend
p + theme(legend.position = "top")

@hadley hadley added this to the v2.3.0 milestone Apr 27, 2018
@hadley hadley changed the title Check on legend text alignment Legend title is incorrectly aligned when horizontal May 1, 2018
@hadley
Copy link
Member Author

@hadley hadley commented May 1, 2018

@clauswilke have you seen this too? I quickly skimmed through your PRs but I didn't see anything that addressed this explicitly

@clauswilke
Copy link
Member

@clauswilke clauswilke commented May 1, 2018

I haven't addressed or modified this in any way. What is happening is that the title is centered relative to the entire legend:

p + theme(legend.position = "top") + 
  theme(legend.spacing.y = grid::unit(50, "cm")) # 50 cm equals to 5 cm because of issue #2398

screen shot 2018-05-01 at 5 49 25 pm

@clauswilke
Copy link
Member

@clauswilke clauswilke commented May 1, 2018

Note that guide_legend() behaves exactly the same:

df <- data.frame(z = 1:5)
p <- ggplot(df, aes(1, 1, colour = factor(z))) + 
  geom_point() + 
  scale_color_discrete(guide = guide_legend(label.position = "bottom"))

# Title should be centered with legend
p + theme(legend.position = "top") + theme(legend.spacing.y = grid::unit(5, "cm"))

screen shot 2018-05-01 at 5 56 08 pm

@hadley
Copy link
Member Author

@hadley hadley commented May 1, 2018

Oh so this probably isn't a regression

@hadley hadley removed this from the v2.3.0 milestone May 1, 2018
@clauswilke
Copy link
Member

@clauswilke clauswilke commented May 6, 2018

The bigger issue, in my mind, is that there is no simple workaround, because the vjust setting is ignored. I'm showing this here with both a discrete and a continuous scale, to show that they behave the same:

library(ggplot2)
p <- ggplot(mtcars, aes(hp, disp, color = mpg, shape = factor(cyl))) +
  geom_point(size = 2) +
  scale_shape_discrete(guide = guide_legend(label.position = "bottom")) + 
  theme(legend.position = "top")
p

screen shot 2018-05-06 at 3 14 39 pm

p + theme(legend.title = element_text(vjust = 1, colour = "red"))

screen shot 2018-05-06 at 3 14 29 pm

(I've colored the legend title red to show that styling the legend title works, only the justification arguments are ignored.)

I'll see if there's a simple way to fix this that doesn't require touching much code. In the long run, I think the legend drawing code needs to be rethought from the ground up, but that's not for 2.3.0.

@ptoche
Copy link

@ptoche ptoche commented May 6, 2018

Workaround of sorts:

library(ggplot2)
ggplot(mtcars, aes(hp, disp, color = mpg, shape = factor(cyl))) +
    geom_point(size = 2) +
    theme(legend.position = "top") +
    guides(shape = guide_legend(label.position = "bottom", 
            title.position = "left", title.vjust = 0.8), 
        color = guide_legend(label.position = "top", 
            title.position = "right", title.vjust=0.4))

Created on 2018-05-07 by the reprex package (v0.2.0).

@clauswilke
Copy link
Member

@clauswilke clauswilke commented May 6, 2018

I now see that there are (at least) two separate issues. One is that vjust and hjust can't be set in the theme but can be set via the guide function. It is a simple fix to allow setting via the theme as well. The second is that the margin settings in legend.title are ignored. This is a problem because if we set vjust to a number other than 1 then the text is moved different amounts for grobs of different heights. I guess the workaround could be to manually fiddle with the title.vjust settings for each guide function until things look right, but if margins could be set that would be better I think.

library(ggplot2)
ggplot(mtcars, aes(hp, disp, color = mpg, shape = factor(cyl))) +
  geom_point(size = 2) + theme(legend.position = "top") +
  guides(color = guide_colorbar(title.vjust = .8),
         shape = guide_legend(title.vjust = .8)) +
  theme(legend.title = 
          element_text(
            debug = TRUE,
            margin = margin(10, 0, 0, 0, "pt") # margin setting is ignored
          )
       )

screen shot 2018-05-06 at 5 57 52 pm

@karawoo
Copy link
Member

@karawoo karawoo commented May 7, 2018

The latter issue about the margins for legend text/titles has been raised in #1502. I tried to tackle that after reworking titleGrob() last year, but wasn't able to wrap my head around the legend code enough to make any headway at the time.

@clauswilke
Copy link
Member

@clauswilke clauswilke commented May 7, 2018

@karawoo I just opened a pull request (#2556) that provides a partial fix for this issue. I hadn't seen #1502 previously and will take a look. My fix for legend titles would likely work for legend text as well. (Meaning: we can use the same technique to fix legend text. But it isn't currently fixed in the pending pull request.)

@flying-sheep
Copy link
Contributor

@flying-sheep flying-sheep commented Dec 7, 2018

Also if you fiddle with title.vjust, the bounding box is unaffected. If you title is higher than the legend, this results in some seriously wrong spacing:

grafik

this is title.vjust = 5 to make the bar line up with the second line of the title.

@ThomasDelSantoONeill
Copy link

@ThomasDelSantoONeill ThomasDelSantoONeill commented Apr 18, 2020

Dear @clauswilke and @hadley
I was wondering how to position the legend title on top of an horizontal scale_colour_gradient key. Is this possible at all? Also it seems that the key does not fill completely.
Cheers in advance!!! :)

image

ggraph(lay.ggraph) +
  geom_edge_link0(aes(color = links$weight), width = links$weight*10, lineend = "round") + 
  scale_edge_color_gradient(name = "Link Strength", low = "#6495ED85", high = "#C1403D85") +
  geom_node_point(shape = 21, fill = "#D3D3D3", 
                  color = "#808080", size = 15, stroke = 2) +
  foodweb_theme +
  theme(legend.position = c(0.9, 0.1),
        legend.direction = "horizontal") +
  labs(y = "TL")
@ThomasDelSantoONeill
Copy link

@ThomasDelSantoONeill ThomasDelSantoONeill commented Apr 19, 2020

Hi again,

I did find a workaround solution. Only a bit of merging trickery was needed between ggraph and ggplot2. Basically everything missing needed to be inserted in the guide = guide_edge_colorbar(...) argument within scale_edge_color_gradient. For the "not enterly filled colorbar" key I set the upper limit a bit more than 1 (i.e. 1.1). Code:

ggraph(lay.ggraph) + 
  geom_edge_link0(aes(edge_colour = links$weight), edge_width = links$weight*10, lineend = "round") +
  scale_edge_color_gradient(name = "Link Strength", low = "#6495ED85", high = "#C1403D85",
                            limits = c(0,1.01),
                            guide = guide_edge_colorbar(title = "Link Strength", title.position = "top",
                                                        title.hjust = 0.5, ticks = TRUE, label = TRUE,
                                                        frame.colour = "black", barwidth = 7.5)) +
  geom_node_point(shape = 21, fill = "#D3D3D3", color = "#808080", size = 15, stroke = 2) +
  labs(y = "TL") +
  foodweb_theme

This produces:

image

All the absolute best!

@thomasp85 thomasp85 added this to the ggplot2 3.3.4 milestone Mar 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants