Understanding when and why Discrete value supplied to continuous scale happens

Hi,
I was trying to include a background annotation in a ggplot but for some reason it throws the discrete value supplied to continous scale error.
if we add a geom blank before annotation it works ( but then the scales limit will depend on whatever data we map to geom blank which is not desired as we want the plot to only show the smooth)
Is there another way to let the annotation start/end from to the plot edges for discrete scales?

require(ggplot2)
#> Loading required package: ggplot2
mtcars$cylf<- as.factor(mtcars$cyl)
ggplot(mtcars, aes(x=cylf, y=mpg))+
  geom_blank()+
  annotate("rect", xmin = -Inf, xmax = Inf,
           ymin = 15,ymax = 30,fill="lightblue")+
geom_smooth(aes(group=-1L) )
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : pseudoinverse used at 0.99
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : neighborhood radius 2.01
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : reciprocal condition number 2.0055e-016
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : There are other near singularities as well. 4.0401
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : pseudoinverse used
#> at 0.99
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : neighborhood radius
#> 2.01
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : reciprocal
#> condition number 2.0055e-016
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : There are other
#> near singularities as well. 4.0401

ggplot(mtcars, aes(x=cylf, y=mpg))+
  annotate("rect", xmin = -Inf, xmax = Inf,
           ymin = 15,ymax = 30,fill="lightblue")+
  geom_smooth(aes(group=-1L) )
#> Error: Discrete value supplied to continuous scale

Created on 2019-03-13 by the reprex package (v0.2.1)

This is happening because you're converting cylinders to a factor (discrete), but you'll still get warnings from geom_smooth() using the default method, because you can't really apply loess to categorical data (which is what factors are/why you encoded cylinder as factors — you can't have part of a cylinder):

library(ggplot2)

ggplot(mtcars, aes(x = cyl, y = mpg)) +
  geom_blank() +
  annotate("rect",
    xmin = -Inf, xmax = Inf,
    ymin = 15, ymax = 30, fill = "lightblue"
  ) +
  geom_smooth(aes(group = -1L))
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : pseudoinverse used at 3.98
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : neighborhood radius 4.02
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : reciprocal condition number 2.0055e-16
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric =
#> parametric, : There are other near singularities as well. 16.16
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : pseudoinverse used
#> at 3.98
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : neighborhood radius
#> 4.02
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : reciprocal
#> condition number 2.0055e-16
#> Warning in predLoess(object$y, object$x, newx = if
#> (is.null(newdata)) object$x else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : There are other
#> near singularities as well. 16.16

Created on 2019-03-13 by the reprex package (v0.2.1)

This Stack Overflow thread might be helpful:

1 Like

This is a simplified reprex example.
In my real plot x axis is categorical by design.
I still need to add a background reference rectangle.
I can try to come us to a closer plot to what I am doing.
E.g. boxplots with a line connecting the medians.

Maybe this example can serve as an easier reference point:

library(ggplot2)

ggplot(diamonds, aes(x = cut, y = price)) +
  geom_boxplot() +
  annotate("rect",
    xmin = -Inf, xmax = Inf,
    ymin = 15, ymax = 15000, fill = "lightblue",
    alpha = .2
  )


class(diamonds$cut)
#> [1] "ordered" "factor"
str(diamonds$cut)
#>  Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...

Created on 2019-03-13 by the reprex package (v0.2.1)

Also, do take a look at the Stack Overflow thread I linked, as I think it's closer to the problem you're describing.

Yes my problem is that the annotation "background" layer should come first and not sure how to make ggplot work with that without the geom_blank hack but then the y/x scale would reflect x/y ranges and not just the stat layer that is added afterwards.

Thanks for the discussion, this accidentally solved the problem I just had!!
I also treat the x-axis as factor (for resorting) - but maybe I should try to find another solution.

see how it errors when we do the following and how the factors are reordered when we use the factor levels as xmin and xmax and the annotation does not start from plot edge

require(ggplot2)
#> Loading required package: ggplot2

ggplot(diamonds, aes(x = cut, y = price)) +
  annotate("rect",
           xmin = -Inf, xmax = Inf,
           ymin = 15, ymax = 15000, fill = "lightblue",
           alpha = .2
  )+
  stat_summary(data=diamonds,fun.y="median",geom="line",mapping = aes(group=1L))
#> Error: Discrete value supplied to continuous scale


ggplot(diamonds, aes(x = cut, y = price)) +
  annotate("rect",
           xmin = "Fair", xmax = "Ideal",
           ymin = 15, ymax = 15000, fill = "lightblue",
           alpha = .2
  )+
  stat_summary(data=diamonds,fun.y="median",geom="line",mapping = aes(group=1L))

Created on 2019-03-13 by the reprex package (v0.2.1)

I do. I don't have a solution for you at this point, though. Have you browsed the issues in the GitHub repo to see if there are any open threads related to this? This actually might be somewhat related, but I'm not 100% sure.

If there's nothing else, you can file a new issue.

filed a new issue:

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.