Skip to content

ggplot2: Three Variable Time Series Panel Chart

May 18, 2009

The three variable time series panel chart published in Charts & Graphs blog conveniently combines different chart formats and colour formatting.

Next, a similar chart will be constructed in ggplot2.

First, import the data file and convert it to a long format. After that representations of different subsets of data will be added layer-by-layer.

> library(ggplot2)
> df <- read.csv("Consol_GISS_SATO_Nino34A_RSS.csv")
> df[, "GISS_A_C"] <- NULL
> dfm <- melt(df, id.vars = c(1:3), na.rm = TRUE)

A few things to note here:

  • scale_colour_identity() maps the colours to the colour variables, i.e. variable with the value “red” will be plotted in red.
  • as.table=FALSE argument in facet_grid() is used to reverse the order of facets.
> f <- ggplot(dfm, aes(yr_frac, value, ymin = 0,
     ymax = value, colour = "grey30")) + scale_colour_identity() +
     xlim(1980, 2010) + facet_grid(variable ~
     ., scales = "free", as.table = FALSE) +
     theme_bw() + opts(panel.margin = unit(0,
     "lines"), axis.title.x = theme_blank(),
     axis.title.y = theme_blank())
> f1 <- f + geom_step(subset = .(variable ==
> f2 <- f1 + geom_linerange(subset = .(variable ==
> NINO34 <- subset(dfm, dfm$variable == "NINO34A")
> f3 <- f2 + geom_linerange(data = NINO34, aes(colour = ifelse(value <
     0, "blue", "red"))) + opts(title = "RSS and NINO3.4 Temperature Anomalies \nand SATO Index Trends Since 1980")
> f3
19 Comments leave one →
  1. douglas permalink
    May 20, 2009 6:24 pm

    Shouldn’t the year labels be centered between the tickmarks that indicate the beginning and the end of each year?

    • learnr permalink
      May 20, 2009 6:40 pm

      I don’t quite understand what you mean – currently the tick marks and labels are every five years.

      If this was monthly data, and the tick marks were indicating the beginning and the end of each year, then, yes, the labels should be centered between the tick marks.

  2. d^2 permalink
    May 22, 2009 5:37 pm

    have you had any luck overlaying charts? it isn’t immediately obvious to me how to do it.

    i have plenty of circumstances where i want to plot a bunch of points and then overlay (or underlay) some kind of boxplot or curve on them, but i’m having trouble finding out how to do it from the docs for ggplot.

    • learnr permalink
      May 24, 2009 1:18 am

      ggplot2 is designed to work in a layered fashion. So to accomplish the task you are describing you first plot the points, and then add another layer with for example boxplot.

      Consider the following example:
      dx <- data.frame(x=1:10, y=sample(10))
      ggplot(dx, aes(x, y)) + geom_point(size=4) + geom_line()

      The resulting plot consists of three layers: the raw data layer, points layer and lines layer. You can add as many layers as you wish.

      • d^2 permalink
        May 26, 2009 5:07 pm

        how about if you wanted to overlay a different dataset on top of what you have above?

      • learnr permalink
        May 26, 2009 5:48 pm

        In overlaying a different dataset, it needs to be mapped to the layer (this overrides the original mapping), and if the data structure is different than that in the original dataset, new mappings need to be created.

        See example below where three different datasets are overlaid on the same plot: each layer is mapped to a different dataset.

        dx <- data.frame(x=1:10, y=sample(10))
        dy <- data.frame(a=1:10, b=sample(11:20))
        dz <- data.frame(f=1:10, g=-sample(10))

        ggplot(dx, aes(x, y)) +
        geom_point(size = 4) +
        geom_point(data = dy, aes(a, b), colour= "red") +
        geom_line(data = dz, aes(f, g), colour = "steelblue", linetype = 2, size = 2)

  3. d^2 permalink
    May 26, 2009 11:32 pm

    aha, i think i see how it works. if you change the mapping, do all subsequent layers refer to that mapping unless otherwise specified?

    thank you!

    • learnr permalink
      May 27, 2009 12:22 am

      Yes, if no specific mapping exists on a layer then it refers back to the default mapping specified in the initial ggplot() call.

      There’s a good explanation of mapping in Chapter 4 of the forthcoming ggplot2 book.

  4. Daniel Fernandez permalink
    November 5, 2009 12:10 am


    How would you overlay for example RSS and SATO with different colors and then have a legend????

  5. nick permalink
    December 7, 2010 1:11 am

    Any sense of how one might add a shaded interval to the above graph? Say you wanted to draw particular attention to 1990-2000. Could you use geom_rect() to do this, somehow? Furthermore, could how might you achieve this on just one of the three graphs, or on all of them?

    • learnr permalink*
      December 7, 2010 2:14 am

      Yes, geom_rect() is perfectly suitable for highlighting a particular period. If you want to do this on three graphs, then the best option would be to create a new data frame with the necessary data, and then base the geom_rect() layer on this.

  6. April 16, 2013 10:36 pm

    Is it possible to add y axis labels for each plot? (labeling the units for example)

    • learnr permalink*
      June 6, 2013 9:52 am

      There is no straightforward way to accomplish this, as far as I can see. I would like to be proved wrong, though.

      • February 15, 2014 1:47 am

        Hi, thanks for this example. It is really useful for the kind of I am currently trying to produce.

        My question is the same: any way to insert independent y-axis labels? It’s been a long since your last response, so I thought that maybe there’s a new feature on ggplot2 that allows that.

  7. Jen permalink
    January 14, 2015 2:38 am

    I’m having trouble reproducing this trick. Before I make a reproducible example and ask the world at large, I see that this example uses the old “opts” format. Is there something in this code that might break now? I can’t see why but darned if I know what’s wrong, something in the subset function (currently it makes extra blank panels for all the variables that aren’t being called in the subset) and I don’t know how to leave them out.

    pbase <- ggplot(dat, aes(x = year, y = value, ymin = 0, ymax = value)) + theme_bw() +
    facet_grid(variable ~ ., scales="free_y")
    p1 <- pbase + geom_line(subset = .(variable == "totalpop"))


  1. Area Plots with Intensity Coloring ~ el nino SST anomalies w/ ggplot2 « mind of a Markov chain
  2. ggplot2: Three Variable Time Series Panel Chart (via Learning R) | Human Mathematics
  3. A ggplot trick to plot different plot types in facets « Stat Bandit
  4. A ggplot trick to plot different plot types in facets | StatBandit

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: