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

geom_vline messes up geom_line legend, if show_guide = TRUE #1267

Closed
maxheld83 opened this issue Aug 16, 2015 · 9 comments
Closed

geom_vline messes up geom_line legend, if show_guide = TRUE #1267

maxheld83 opened this issue Aug 16, 2015 · 9 comments

Comments

@maxheld83
Copy link

@maxheld83 maxheld83 commented Aug 16, 2015

Let's say I have some line graph via geom_line and would like to add some geom_vlines as thresholds.
Let's further say that I have several such geom_vlines and would therefore require a legend.

Here's the base layer plot:

library(ggplot2)
data(mpg)

# base plot
g <- ggplot()
g <- g + geom_line(data = mpg, mapping = aes(y = cty, x = year, color = manufacturer), stat = "summary", fun.y = mean)
g

So far, so good:

baseplot


Now let's try and add the threshold via geom_hline with a custom legend:

# add threshold via geom_hline()
g + geom_vline(aes(xintercept = 2004, linetype = "Funny Law"), show_guide = TRUE) + scale_linetype_manual(values = c("Funny Law" = "dashed"))  # screws up all geom_line legends

Not so great, the base-layer legends are all screwed up:

geomhline


Ok, let's see whether we can make this work via geom_linerange() with separate dataframes:

thresholds <- data.frame(threshold = "Funny Law", year = 2004, ymin = 0, ymax = 35)
g + geom_linerange(data = thresholds, mapping = aes(x = year, ymin = ymin, ymax = ymax, linetype = threshold))  # works ok

Works ok, except that the geom_linerange doesn't fill the entire y-height of the plot, but ok:

linerange


Then wouldn't we expect the same approach to work via geom_vline() with a separate dataframe?

# add threshold via geom_hline() WITH separate data
g + geom_vline(data = thresholds, mapping = aes(xintercept = year, linetype = threshold), show_guide = TRUE)  # screws up all geom_line legends

Nope, the same problem with screwed up legends returns:

vlinesep


Bug or my mistake?


May be related:

@maxheld83
Copy link
Author

@maxheld83 maxheld83 commented Aug 16, 2015

updated, because earlier version was too complicated.

@hadley
Copy link
Member

@hadley hadley commented Aug 17, 2015

Here's an even simpler example:

df <- data.frame(x = c(1, 2), y = c(1, 2), z = c("a", "b"))

threshold <- data.frame(x = c(1.2, 1.5), name = c("bar", "foo"))
ggplot(df, aes(x, y, colour = z)) + 
  geom_point() + 
  geom_vline(aes(xintercept = x, linetype = name), show.legend = TRUE, data = threshold)
@hadley hadley closed this in e12f8dd Aug 17, 2015
@hadley
Copy link
Member

@hadley hadley commented Aug 17, 2015

There are a couple of problems here. There's a bug in the legend generation code which means that the legends where inheriting aesthetics when they shouldn't. There's another problem that show.legend = TRUE forces inclusion on every legend. But that problem goes away if geom_vline() defaults to show.legend = NA.

Both these cases now work:

df <- data.frame(x = c(1, 2), y = c(1, 2), z = c("a", "b"))
ggplot(df, aes(x, y, colour = z)) + 
  geom_point() + 
  geom_vline(xintercept = 1.5))

threshold <- data.frame(x = c(1.2, 1.5), name = c("bar", "foo"))
ggplot(df, aes(x, y, colour = z)) + 
  geom_point() + 
  geom_vline(aes(xintercept = x, linetype = name), data = threshold)
@rdcomineor
Copy link

@rdcomineor rdcomineor commented Feb 22, 2016

Hello, Unfortunately a problem persists in the legends of the lines if you also have to add a horizontal line:
threshold <- data.frame(x = c(1.2, 1.5), name = c("bar", "foo")) ggplot(df, aes(x, y, colour = z)) + geom_point() + geom_vline(aes(xintercept = 1.25, linetype = "dotted"), data = threshold)+geom_hline(aes(yintercept = 1.75, linetype = "1F"), data = threshold)

Do you have a suggestion how to have just a vertical line, or horizontal line and not a cross in the legends? Many thanks

image

@cyberang3l
Copy link

@cyberang3l cyberang3l commented Dec 1, 2016

Is there any solution to the cross problem demonstrated by @rdcomineor when using both geom_hline and geom_vline?

@ptoche
Copy link

@ptoche ptoche commented Sep 30, 2017

@cyberang3l, I couldn't run the example given by @rdcomineor, but I had a similar problem with geom_linerange() and solved it by inserting show.legend=FALSE: geom_linerange(aes(ymin = y, ymax = x, color = "vline"), show.legend=FALSE) .

The mapping to color still works and this produces a legend for the geom_linerange(), so show.legend=FALSE is not a nuclear option, but it does remove the vertical lines in the legend.

@fmassicano
Copy link

@fmassicano fmassicano commented Mar 14, 2018

The problem still persists if you have hline and vline in the same chart.

@ptoche
Copy link

@ptoche ptoche commented Mar 15, 2018

@fmassicano, as this issue is closed, why don't you post a new issue with a working, minimal example. Also, please post screenshot with the reprex package.

https://github.com/tidyverse/reprex

@lock
Copy link

@lock lock bot commented Sep 11, 2018

This old issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with reprex) and link to this issue. https://reprex.tidyverse.org/

@lock lock bot locked and limited conversation to collaborators Sep 11, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants