Methexis
Methexis

Reputation: 2861

ggplot2 geom_line() and smoothing

I am trying to create a GGPLOT2 smoothed line graph that looks more like this

enter image description here

Source: http://www.esrl.noaa.gov/psd/enso/mei/

and less like this:

enter image description here

Source: https://dl.dropboxusercontent.com/u/16400709/StackOverflow/Rplot02.png

My data are available on dropbox.

Having looked at previous posts I used the code below:

#MEI Line Graph

d4 <- read.csv("https://dl.dropboxusercontent.com/u/16400709/StackOverflow/Data_MEI.csv")
head(d4,n=20)

MEI<-ggplot(d4,aes(x=d4$Date, y=d4$MEI,group=1))+geom_line()

MEI+stat_smooth(method ="auto",level=0.95)

What I think I need is to reduce the amount of smoothing taking place, but I have yet to figure out how to achieve this.

d4s<-SMA(d4$MEI,n=8)
plot.ts(d4s)

SMA() works well but I cant get it to work with ggplot Any hints would be appreciated!

Upvotes: 3

Views: 5591

Answers (1)

Andy Clifton
Andy Clifton

Reputation: 5056

Be aware that the MEI index is for a 2-month period, so it's already got some smoothing built in. Assuming that you are using the MEI data that NOAA ESRL publishes, you should be able to create the same plot.

First of all you need to get the system set up, as you'll be working with timezeones:

# set things up  ----
working.dir = file.path('/code/R/StackOverflow/')
setwd(working.dir)
Sys.setenv(TZ='GMT')

now, download your data and read it in

d.in <- read.csv("MEI.txt")

The next step is to get the dates formatted properly.

d.in$Date <- as.POSIXct(d.in$Date,
                        format = "%d/%m/%Y", 
                        tz = "GMT")

and because we need to figure out where things cross the x-axis, we'll have to work in decimal dates. Use the Epoch value:

d <- data.frame(x = as.numeric(format(d.in$Date,
                                      '%s')),
                y = d.in$MEI)

Now we can figure out the zero-crossings. We'll use Beroe's example for that.

rx <- do.call("rbind",
              sapply(1:(nrow(d)-1), function(i){
                f <- lm(x~y, d[i:(i+1),])
                if (f$qr$rank < 2) return(NULL)
                r <- predict(f, newdata=data.frame(y=0))
                if(d[i,]$x < r & r < d[i+1,]$x)
                  return(data.frame(x=r,y=0))
                else return(NULL)
              }))

and tack that on the end of the initial data:

d2 <- rbind(d,rx)

now convert back to dates:

d2$date <- as.POSIXct(d2$x,
                      origin = "1960-01-01",
                      format = "%s",
                      tz = "GMT")

now we can do the plot:

require(ggplot2)
ggplot(d2,aes(x = date,
              y = y)) + 
  geom_area(data=subset(d2, y<=0), fill="blue") + 
  geom_area(data=subset(d2, y>=0), fill="red") + 
  scale_y_continuous(name = "MEI")

and that gives you this:

enter image description here

Now, do you really need to smooth this?

Upvotes: 10

Related Questions