hartmut
hartmut

Reputation: 982

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

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?)

Upvotes: 10

Views: 4054

Answers (3)

Alexis
Alexis

Reputation: 376

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()

Upvotes: 9

Jake Oliver Stephen
Jake Oliver Stephen

Reputation: 63

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.

Upvotes: 2

Axeman
Axeman

Reputation: 35187

Switch around the order, and bring the data and main aesthetics into your ggplot call. You are basically writing this:

p1 <- ggplot() +
  annotate(geom = "rect", ymin = -Inf , ymax = 10, xmax = 0, xmin = Inf, alpha = .1)

At this point, p1 has a continuous x axis, since you provided numbers here.

p2 <- p1 + geom_boxplot(aes(factor(cyl), mpg), mtcars)

Now you add another layer that has a discrete axis, this yields an error.

If you write it the 'proper' way, everything is OK:

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

p.s.: Also it's not that hard to make a reproducible minimal example that accurately shows your problem, as you can see.

Upvotes: 6

Related Questions