5

I have this plot, which calculates an index of abbundance of a bird species for a given winter: Facet by year This graphic comes from this code (themes and scales excluded):

ggplot (a, aes (pentada,ika,colour=inv,group=inv,na.rm=T)) + geom_line()+
facet_wrap(~inv, ncol=3)+labs(title="SYLATR\n",x="",y="IKA")

and the data frame has 6 variables:

pentada / censos / yr / total / inv / ika

The thing is that I would like to add a line in each of the wintering seasons that shows the mean of the abbundance for all the years combined and I don't know how. should I append the mean as a new column after every wintering season? In this case, how should I do it?.

Thank you.

David Arenburg
  • 91,361
  • 17
  • 137
  • 196
Miguel
  • 67
  • 2
  • 9
  • 2
    Comment on style: coloured lines may look a pretty but you don't need it because the facet name is there on the top of each facet. The legend on the right is then a waste of space, you can get more detail in your graphs without it. – Spacedman Feb 17 '15 at 15:59

1 Answers1

5

I'm not sure if you want the global mean, i.e. averaging over winters as well as days. If so, then shadow's solution above is probably best; something like this would also do:

#toy data
df <- data.frame(t = rep(1:100,9), pop = rnorm(900)+20, 
    year = rep(letters[1:9], 9, each = 100))

#make graph
ggplot(data = df, aes(x = t, y = pop, colour = year, na.rm=T)) + 
    geom_line() + facet_wrap(~year, ncol = 3) + 
    geom_line(aes(x=t, y = mean(pop)))

If you want the mean-over-winters-only, so that there is still a dynamic by day, I think you should probably add that to the data frame first, before calling ggplot.

#aggregate the mean population over years but not days
yearagg.df <- aggregate(data = df, pop ~ t, mean)

#make plot
ggplot(data = df, aes(x = t, y = pop, colour = year, na.rm=T)) + 
    geom_line() + 
    facet_wrap(~year, ncol = 3) + 
    geom_line(data = yearagg.df, aes(y = pop, x=t), color = 'black')

That second code snippet results in this graph:

Graph of 2nd code snippet with mean-over-years-only

UPDATE: You will probably have easier plotting if you put the averaged data back into your data frame so that you can plot all layers from the same data frame instead of mixing/matching data from multiple frames into one plot.

df.m <- merge(df, yearagg.df, by = 't', suffixes = c('.raw', '.mean'))
ggplot(data = df.m, aes(x = t, colour = year, na.rm=T)) + 
    geom_line(aes(y = pop.raw)) + 
    facet_wrap(~year, ncol = 3) + 
    geom_line(aes(y = pop.mean), color = 'gray')
Curt F.
  • 4,690
  • 2
  • 22
  • 39
  • this is what I was looking for, but for some reason I get an error:Error: ggplot2 doesn't know how to deal with data of class uneval – Miguel Feb 17 '15 at 16:50
  • The first solution just makes an horizontal line, I was looking for something like in the second solution: so I can compare directly the mean over all the years against a given year. – Miguel Feb 17 '15 at 16:58
  • I had a typo in the last line of code which I edited to fix. Instead of just `'black'`, it should have said `color = 'black'`. Hopefully that was the cause of the error. – Curt F. Feb 17 '15 at 16:59
  • Ok! I correct that, but now I have another error!! Error: Aesthetics must either be length one, or the same length as the dataProblems:inv this is the code ggplot (data=a, aes(pentada, ika, colour = inv, group=inv, na.rm=T)) + geom_line() + facet_wrap(~inv, ncol = 3)+ geom_line(data=yearagg.df, aes(pentada, mean(ika)), colour="black") Any hint? (sorry for the poor editing) – Miguel Feb 17 '15 at 17:14
  • All the variables in the `aes()` call inside the `geom_line()` on `yearagg.df` will actually have to exist in `yearagg.df`. Or, you can use `merge` to add the `yearagg.df` data to your original data frame so you don't have to invoke `geom_line()` on a completely different data frame to get the lines you want. I'll update my answer with this `merge` approach. – Curt F. Feb 17 '15 at 17:22
  • Wow!!! just what I needed (in the code it's a "group=inv" missing after the colour. Thanks for the teaching!. – Miguel Feb 17 '15 at 17:38
  • Feel free to accept my answer if it met all your needs. In addition to the nice reputation bonus for me, it will keep other users from adding more answers that you probably won't find helpful, and will indicate to future browsers that this question is solved. – Curt F. Feb 17 '15 at 17:49