1

The following describes in a simplified manner an issue into which I run often but never get it to work. It has to do with superposing layers with different information.

Any help is appreciated.

library(dplyr)
library(ggplot2)

df = data.frame(id = c(1,1,1,1,2,2,2,3,3,3), 
            year = c(2000,2001,2002,2003,2000,2001,2002,2001,2002,2003),
            meas = c(1.1,1.2,NA,1.4,2.1,1.9,1.8,3.1,3.0,3.3))

df$id   = as.factor(df$id)
df$year = as.factor(df$year)

tib = as.tbl(df)

which produces the tibble:

# A tibble: 10 x 3
       id   year  meas
   <fctr> <fctr> <dbl>
 1      1   2000   1.1
 2      1   2001   1.2
 3      1   2002    NA
 4      1   2003   1.4
 5      2   2000   2.1
 6      2   2001   1.9
 7      2   2002   1.8
 8      3   2001   3.1
 9      3   2002   3.0
10      3   2003   3.3

Presently, I compute the median of the meas-ures for each year in the cross section.

tib2 = tib %>% group_by(year) %>%       
    summarise(medi=median(meas,na.rm=T))
tib2

Which gives as expected

# A tibble: 4 x 2
    year  medi
  <fctr> <dbl>
1   2000  1.60
2   2001  1.90
3   2002  2.40
4   2003  2.35

So far so good. Now, I create my first plot

p = ggplot(tib, aes(x = year, y = meas, group = id, color = id)) p = p + geom_line() p which produces

enter image description here

On the other hand, the following produces a set of fat dots as it should

p1=ggplot(tib2, aes(x = year, y = medi)) + geom_point(colour = 'red', size = 3)
p1

Red dots

I try however to place the red dots in the first figure like so:

p = p + geom_point(data = tib2, aes(x = year, y = medi), colour = 'red', size = 3)
p

This is where I get the error:

Don't know how to automatically pick scale for object of type function. Defaulting to continuous. Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, the arguments imply different numbers of lines : 4, 0

Remark: I noticed that the missing value induces a cut in the red line which I might wish to interpolate. When I replace the NA by some value, the error persists however.

4
  • 1
    shouldn't that last code chunk be p = p + geom_point(...)? Commented May 8, 2018 at 9:53
  • The "object of type function" error suggests that aes(x = year...) might be misinterpreted (is lubridate loaded by any chance?) What happens if you do ggplot() + geom_line(data = tib2, aes(x = year, y = medi), colour = 'red', size = 3) Commented May 8, 2018 at 9:55
  • Lubridate is not on. I made a mistake copying. The error persists with p=p+geom_point. Commented May 8, 2018 at 10:00
  • ggplot()+geom_point(data = tib2, aes(x = year, y = medi), colour = 'red', size = 3) produces the second figure. It is when I add p=p+geom_point(data = tib2, aes(x = year, y = medi), colour = 'red', size = 3) that I get the bug. Thanks Commented May 8, 2018 at 10:03

2 Answers 2

3

The "object of type function" error relates to the dplyr::id() function.

When you assign an aesthetic in the ggplot call it applies to all the plot, and while it is correctly interpreted in the first geom in the tib dataframe context, the tib2 context does not have it, so it produces an error.

You can pass the relevant aes to the single geom, or you can use inherit.aes = FALSE on the 'tib2 geom':

library(ggplot)

ggplot(tib) + 
  geom_line(aes(x = year, y = meas, group = id, color = id)) +
  geom_point(data = tib2, aes(x = year, y = medi), size = 3, color = 'red')


ggplot(tib, aes(x = year, y = meas, group = id, color = id)) + 
  geom_line() +
  geom_point(data = tib2, aes(x = year, y = medi), size = 3, color = 'red', inherit.aes = FALSE)

Or even more elegantly, specify the aes that are common in the ggplot call and the others where needed:

ggplot(tib, aes(x = year)) + 
  geom_line(aes(y = meas, group = id, color = id)) +
  geom_point(data = tib2, aes(y=medi), size = 3, color = 'red')

Created on 2018-05-08 by the reprex package (v0.2.0).

Sign up to request clarification or add additional context in comments.

2 Comments

To avoid mistakes, would it make sense to follow the following rule: put the first dataframe into ggplot. Put aesthetics in geom as they come along. To change dataframe, put new dataframe+aes in new geom?
That's what I usually do. Also changing data in geom should be done sparingly
2

you can try

ggplot(tib, aes(x = year, y = meas, group = id, color = id)) +
   geom_line() +
   stat_summary(fun.y = median, geom="point", aes(group=year), colour = 'red', size = 3)

enter image description here

or use as Dash2 recommended

ggplot() +
   geom_line(data=tib, aes(x = year, y = meas, group = id, color = id)) +
   geom_point(data = tib2, aes(x = year, y = medi), colour = 'red', size = 3) 

1 Comment

thanks! This fixes the bug. The mistake must be that by defining within ggplot the data = tib it persists as I introduce the new data. This implies one cannot just add layers, from the beginning the intention should be clear. Unless there is a parameter I missed. Thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.