ggplot - annotate() - "Discrete value supplied to continuous scale"

Viewed 3050

I ve read many SO Answers regarding what can cause the error "Discrete value supplied to continuous scale" but I still fail to solve the following issue. In my case, the error is caused by using annotate(). If get rid of + annotate(...) everything works well. Else the error is raised.

My code is as follows:

base <- ggplot() + 
     annotate(geom = "rect", ymin = -Inf , ymax = 0, xmax = 0, xmin = Inf, alpha = .1)
annotated <- base + 
     geom_boxplot(outlier.shape=NA, data = technicalsHt, aes(x = name, y = px_last))
> base  # fine
> annotated
Error: Discrete value supplied to continuous scale

Unfortunately, I cannot give the code leading to the dataframe used here (viz. technicalsHt) bacause it is very long and reliant on APis. A description of it:

> str(technicalsHt)
'data.frame':   512 obs. of  3 variables:
 $ date   : Date, format: "2016-11-14" "2016-11-15" ...
 $ px_last: num  1.096 0.365 -0.067 0.796 0.281 ...
 $ name   : Factor w/ 4 levels "Stock Price Strength",..: 1 1 1 1 1 1 1 1 1 1 ...

> head(technicalsHt)
        date     px_last                 name
1 2016-11-14  1.09582090 Stock Price Strength
2 2016-11-15  0.36458685 Stock Price Strength
3 2016-11-16 -0.06696111 Stock Price Strength
4 2016-11-17  0.79613481 Stock Price Strength
5 2016-11-18  0.28067475 Stock Price Strength
6 2016-11-21  1.10780834 Stock Price Strength

The code without annotate works perfectly:

    base <- ggplot() 
    annotated <- annotated + 
      geom_boxplot(outlier.shape=NA, data = technicalsHt, aes(x = name, y = px_last))
    > annotated   # fine

I tried playing around with technicalsHt, e.g. doing the following:

technicalsHt[,3] <- "hi"
technicalsHt[,2] <- rnorm(ncol(technicalsHt), 2,3)

but no matter what, using a annotate statement raises the error.

EDIT: following the answer below, I tried to put the data and aes in the initial ggplot call, and have geom_boxplot from the outset:

base <-                                  
# also tried: base <- ggplot(data = technicalsHt, aes(x = factor(name), y = px_last)) + geom_boxplot(outlier.shape=NA)
annotated <- base + ggplot(data = technicalsHt, aes(x = name, y = px_last)) + geom_boxplot(outlier.shape=NA)
  annotate(geom = "rect", ymin = -Inf , ymax = 0, xmax = 0, xmin = Inf, alpha = .1)

this works but it is not really satisfactory since the annotation layer (shading part of the coordinate system) then covers the boxes.

(While e.g., that link also mentions this error in connection with annotate, the answer given there does not solve my issue, so I would be extremely grateful for help. First of all, which of the variable is causing problem?)

3 Answers

I had this issue and did not find the answer I wanted, so here is my solution. This is a bit prettier than plotting two times the boxplot.

If you want to annotate a rectangle below the points when there is a discrete scale you need to specify that to ggplot

ggplot(mtcars, aes(factor(cyl), mpg)) + 
  scale_x_discrete() +
  annotate(geom = "rect", ymin = -Inf , ymax = 10, xmax = 0, xmin = Inf, alpha = .1) +
  geom_boxplot()

In response to the layering, the easiest work around that i have found is simply plotting the same box plot twice. I am aware that it is unnecessary code, but it is a very quick fix for the layering issue.

ggplot(mtcars, aes(factor(cyl), mpg)) + 
  geom_boxplot() +
  annotate(geom = "rect", ymin = -Inf , ymax = 10, xmax = 0, xmin = Inf, alpha = .1) + 
  geom_boxplot()

I cannot notice any image degradation from it as the pixels perfectly overlap. Feel free to correct me if anyone has a UHD monitor.

Related