Adding moving averages to ggplot with multiple plots in one window

2,924 views
Skip to first unread message

Anna Zakrisson Braeunlich

unread,
Jul 20, 2014, 2:02:58 PM7/20/14
to ggplot2
Dear ggplot2 group,

I would like to add a 5year moving average to my plot (dummy data and code below). I have multiple plots in one window and would like to have a separate moving average for each factor (stuff1, stuff2 and stuff3 in code below).
I would very much appreciate any help you could give me. The original data points need to stay in the plot with the moving averages overlaid.

with kind regards
Anna Zakrisson

# code and dummy data:
#### Question: how to add moving average (over 5 years) overlaid on the data points.

mydata<- data.frame(
  Year = factor(rep(c("1980","1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989",
                      "1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999", 
                      "2000", "2001", "2002", "2003",
                      "2004", "2005", "2006", "2007", "2008", "2009"), each = 1)), #better way to do this? i am terrible at basic R
  Type = factor(rep(c("stuff1", "stuff2", "stuff3"), each = 10*3)),
  Value = rnorm(90, mean = rep(c(1:90), each = 1),
                sd = rep(c(6, 7, 3), each = 10)))

Value=c(1:90))

library(ggplot2)
p <- ggplot(mydata, aes(x=Year, y=Value))+
  geom_point(mapping=aes(shape=Type), size=2)+
  theme_bw()+
  geom_line(mapping=aes(linetype=Type))+
  ylab(expression(paste("mean ",mu, "g",C~L^{-1}, day^{-1})))+
  theme(legend.key = element_blank())
p

Anna Zakrisson Braeunlich
PhD student

Department of Ecology, Environment and Plant Sciences
Stockholm University
Svante Arrheniusv. 21A
SE-106 91 Stockholm
Sweden/Sverige

Lives in Berlin.
For paper mail:
Katzbachstr. 21
D-10965, Berlin
Germany/Deutschland

E-mail: anna.za...@su.se
Tel work: +49-(0)3091541281
Mobile: +49-(0)15777374888
LinkedIn: http://se.linkedin.com/pub/anna-zakrisson-braeunlich/33/5a2/51b

><((((º>`•. . • `•. .• `•. . ><((((º>`•. . • `•. .• `•. .><((((º>`•. . • `•. .• `•. .><((((º>

Dennis Murphy

unread,
Jul 20, 2014, 4:36:33 PM7/20/14
to Anna Zakrisson Braeunlich, ggplot2
Here's one attempt. I changed Year to numeric because it makes no
sense to me to label every year over a 30 year span. Too much visual
clutter.

mydata<- data.frame(
Year = 1980:2009,
Type = factor(rep(c("stuff1", "stuff2", "stuff3"), each = 10*3)),
Value = rnorm(90, mean = seq(90),
sd = rep(c(6, 7, 3), each = 10)))

library(zoo)
library(plyr)

# rollmean() is a function from the zoo package that computes
# moving averages. The second argument indicates the number
# of values to average at a time.

f <- function(d)
{
require(zoo)
data.frame(Year = d$Year[5:length(d$Year)],
mavg = rollmean(d$Value, 5))
}

# Apply the function to each group
madf <- ddply(mydata, "Type", f)

library(ggplot2)
ggplot(mydata, aes(x=Year, y=Value)) +
geom_point(mapping=aes(shape=Type), size=2) +
theme_bw() +
geom_line(data = madf, mapping=aes(x = Year, y = mavg, linetype=Type,
color = Type), size = 1) +
ylab(expression(paste("mean ",mu, "g",C~L^{-1}, day^{-1}))) +
theme(legend.key = element_blank())


Dennis
> --
> --
> You received this message because you are subscribed to the ggplot2 mailing
> list.
> Please provide a reproducible example:
> https://github.com/hadley/devtools/wiki/Reproducibility
>
> To post: email ggp...@googlegroups.com
> To unsubscribe: email ggplot2+u...@googlegroups.com
> More options: http://groups.google.com/group/ggplot2
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ggplot2" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ggplot2+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Ben Bond-Lamberty

unread,
Jul 20, 2014, 5:32:13 PM7/20/14
to ggplot2
P.S. to Dennis's example: if (like me) you don't normally need zoo,
here's a one-line moving average function that uses base R.

# n is window size; s=1 (for backward only) or 2 (centered window)
ma <- function( x, n=5, s=1 ){ as.numeric( filter( x, rep( 1/n, n ),
sides=2 ) ) }

Ben
Reply all
Reply to author
Forward
0 new messages