Skip to content

Continuous values don't work with scale_shape_identity #402

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

Closed
wch opened this issue Feb 10, 2012 · 10 comments
Closed

Continuous values don't work with scale_shape_identity #402

wch opened this issue Feb 10, 2012 · 10 comments
Milestone

Comments

@wch
Copy link
Member

wch commented Feb 10, 2012

Commit f175bbb broke R CMD check:

df2 <- data.frame(x = 1:5 , y = 1:25, z = 1:25)
s <- ggplot(df2, aes(x = x, y = y))
s + geom_point(aes(shape = z), size = 4) + scale_shape_identity()
# Error: Continuous value supplied to discrete scale
@BrianDiggs
Copy link
Contributor

Shape is inherently discrete; the fact that you can't use a continuous variable isn't surprising. What ought it do?

@wch
Copy link
Member Author

wch commented Feb 10, 2012

Prior to f175bbb, it produced a chart of all the point shapes from 1-25, by using the z value for the shape. I'm not sure if this is "correct" or not. But since shapes are identified by numbers, it seems like you'd want to be able do something like this.

UPDATE: this part about as.integer() working is wrong. It doesn't work.

It is possible to make it work by using as.integer(z):

s + geom_point(aes(shape = as.integer(z)), size = 4) + scale_shape_identity()

It seems to me there are a few alternatives:

  1. Just fix the example so R CMD check will run.
  2. When a numeric vector is passed to a discrete scale, throw an error that conveys information like, "Did you mean for your (continuous) numeric vector to be a (discrete) integer vector? If so, use as.integer()." Also, fix the example.
  3. When a numeric vector is passed to a discrete scale, if it's all integer values, go ahead and use it, coercing with as.integer(); if it's not all integers, throw an error.

@hadley
Copy link
Member

hadley commented Feb 10, 2012

I think option 3 is the right one for shape scales. I made this change because the previous behaviour had broken one of the tests.

@wch
Copy link
Member Author

wch commented Feb 14, 2012

I put a function in stat-bindot.r called is.wholenumber that will check whether a number is a whole number, with some tolerance for FP error. (I took the function from the ?integer page.) It might be a good idea to move it to, say, utilities.r and make use of it here.

@hadley
Copy link
Member

hadley commented Feb 20, 2012

We also need to supplement the tests so this doesn't happen again.

@wch
Copy link
Member Author

wch commented Feb 21, 2012

Hm, I was actually wrong -- wrapping it with as.integer() doesn't actually make a difference. I think I had actually switched to a different version of ggplot2 when I was doing that test.

At any rate, after playing with this some more, I think there are two challenges:

  • issues with the legend. When the code worked (as in 0.9.0) it generated the image with a table of points, but there was no legend. Even if there were a legend, it would just be labeled 1, 2, 3, etc -- not very meaningful.
  • In order to make things work, I think things need to be changed in the scales package. Specifically, the train_discrete function in scale-discrete.r would need to be modified to accept numerics in the way described in option 3 above. This will affect other aesthetics other than shape, so it's important to decide whether this integer-only behavior should be used for all discrete identity scales.

At any rate, here's a test:

test_that("shape identity scale works for numerics", {
  ssi <- scale_shape_identity()

  expect_identical(scale_train(ssi, 1:5), 1:5)

  expect_error(scale_train(ssi, c(.5, 1:4)))
})

If you don't think that the scales package should be changed, here's a quick fix for the code that's breaking R CMD check:

df2 <- data.frame(x = 1:5 , y = 1:25, z = 1:25)
s <- ggplot(df2, aes(x = x, y = y))
s + geom_point(aes(shape = as.character(z)), size = 4) + 
  scale_shape_manual(breaks = as.character(df2$z), values = df2$z, guide = FALSE)

@hadley
Copy link
Member

hadley commented Feb 21, 2012

Hmmm, probably just best to change the example. Otherwise we'd need to muck with a custom scale class for shape identity.

@hadley hadley closed this as completed in c388795 Feb 21, 2012
@hadley
Copy link
Member

hadley commented Feb 21, 2012

This turned out to be much simpler than I thought - and should slightly improve performance with identity scales.

@jmccreight
Copy link

df2 <- data.frame(x = 1:5 , y = 1:25, z = 1:25)
s <- ggplot(df2, aes(x = x, y = y))
s + geom_point(aes(shape = z), size = 4) + scale_shape_identity()
s + geom_point(aes(shape = z, color=z), size = 4) + scale_shape_identity() + scale_color_discrete()
# Error: Continuous value supplied to discrete scale
This time it's for scale_color_discrete. Integer is a discrete variable. Same complaint, different scale.
Thanks!

@hadley
Copy link
Member

hadley commented Sep 11, 2015

@jmccreight can you please open a new issue rather than commenting on a very old issue.

@lock lock bot locked as resolved and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants