Skip to content

Loading…

geom_hline: inherit.aes is always FALSE #426

Closed
wch opened this Issue · 5 comments

3 participants

@wch
Collaborator
wch commented

For geom_hline, vline, and abline, inherit.aes is always FALSE. I can see an advantage: when drawing data from a different data frame, it won't attempt to map possibly nonexistent variables to x and y. However, there are a few drawbacks:

  • Behavior is inconsistent with other geoms.
  • Aesthetics such as colour and yintercept can't be inherited and must be respecified for the geom. This is especially strange if the values are drawn from the original data frame.
mtcar_means <- ddply(mtcars, .(cyl), summarise, mpg = mean(mpg))
# cyl      mpg
#   4 26.66364
#   6 19.74286
#   8 15.10000

# All black lines
ggplot(mtcars, aes(x=disp, y=mpg, colour=factor(cyl))) + geom_point() +
  geom_hline(aes(yintercept=mpg), data=mtcar_means)

# Need to respecify mapping to get colored lines
ggplot(mtcars, aes(x=disp, y=mpg, colour=factor(cyl))) + geom_point() +
  geom_hline(aes(yintercept=mpg, colour=factor(cyl)), data=mtcar_means)

It appears impossible to set inherit.aes=TRUE. I think this is because the value is hard-coded in the $new functions for each geom. If it is indeed desired to have them not inherit by default, I think a better way is to set the default value inherit.aes=FALSE, instead of hard-coding it.

# Can't set inherit.aes=TRUE
ggplot(mtcars, aes(x=disp, y=mpg, colour=factor(cyl))) + geom_point() +
  geom_hline(aes(yintercept=mpg), data=mtcar_means, inherit.aes=TRUE)
# Error in get(x, envir = this, inherits = inh)(this, ...) :
#   formal argument "inherit.aes" matched by multiple actual arguments
@hadley
Owner

I think the best solution is to split geom_hline into geom_hline for when you want to map the position of the line to a variable in your data and annotate_hline for when you have a vector of positions.

@wch
Collaborator
wch commented

Could we just use annotate to do this? I tried running this code, but it doesn't work:

ggplot(mtcars, aes(x=disp, y=mpg, colour=factor(cyl))) + geom_point() +
  annotate("hline", yintercept=20)
# Error in is.unit(y1) : object 'yend' not found

I think it has something to do with GeomHline$new not getting called when you use annotate().

@hadley
Owner

Yes, but I think it needs some re-writing of the geom_hline code because it tries to automatically figure out if you want a annotation or a data-based geom.

@BrianDiggs

Here is another issue which comes about because inherit.aes is fixed to FALSE. If xintercept is specified as a function (or character name of a function), then the mapping must be respecified so that the summary function can find the data.

Consider:

p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()

p + geom_vline(xintercept=3)
p + geom_vline(xintercept=mean)
p + geom_vline(xintercept=mean, inherit.aes=TRUE)
p + geom_vline(xintercept=mean, aes(x=wt))

The first works as expected. The second gives

> p + geom_vline(xintercept=mean)
Warning messages:
1: In mean.default(data[[var]]) :
  argument is not numeric or logical: returning NA
2: Removed 1 rows containing missing values (geom_segment). 

The third gives

> p + geom_vline(xintercept=mean, inherit.aes=TRUE)
Error in get(x, envir = this, inherits = inh)(this, ...) : 
  formal argument "inherit.aes" matched by multiple actual arguments

The forth works.

The pattern is identical for geom_hline (substituting yintercept for xintercept):

p + geom_hline(yintercept=23)
p + geom_hline(yintercept=mean)
p + geom_hline(yintercept=mean, inherit.aes=TRUE)
p + geom_hline(yintercept=mean, aes(y=mpg))

It is worth noting that using stat_vine or stat_hline instead of the geom_ versions work as expected in all cases because the stat_ versions do not have inherit.aes set to FALSE

# all work without error
p + stat_vline(xintercept=3)
p + stat_vline(xintercept=mean)
p + stat_vline(xintercept=mean, inherit.aes=TRUE)
p + stat_vline(xintercept=mean, aes(x=wt))

p + stat_hline(yintercept=23)
p + stat_hline(yintercept=mean)
p + stat_hline(yintercept=mean, inherit.aes=TRUE)
p + stat_hline(yintercept=mean, aes(y=mpg))

This comment was inspired by the StackOverflow question http://stackoverflow.com/q/18786161/892313

@hadley
Owner

This sounds like a great feature, but unfortunately we don't currently have the development bandwidth to support it. If you'd like to submit a pull request that implements this feature, please follow the instructions in the development vignette.

@hadley hadley closed this
@has2k1 has2k1 added a commit to has2k1/ggplot that referenced this issue
@has2k1 has2k1 Get geoms abline, hline and vline working
- These geoms still have same type of issues as ggplot2.
  hadley/ggplot2#426
  This is a badge-of-honor :)
cbc8c77
@has2k1 has2k1 added a commit to has2k1/ggplot that referenced this issue
@has2k1 has2k1 Get geoms abline, hline and vline working
- These geoms still have same type of issues as ggplot2.
  hadley/ggplot2#426
  This is a badge-of-honor :)
bdc29b1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.