7

I would like to use ggplot2 to plot 3 time series in the same graph. I'd like to plot the first 2 series as solid lines without points. And I would like to plot the third series with points only and no line. How can I do that?

library(ggplot2)
library(reshape2)

d1 <- c(1, 2, 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 1)
d2 <- c(0, 2, 4, 5, 4, 3, 2, 4, 6, 7, 6, 5, 3, 1)
d3 <- c(0, 1, 2, 4, 4, 2, 1, 3, 4, 7, 8, 3, 5, 0)

ts1 <- ts(d1, c(2015, 01), c(2016, 03), frequency = 12)
ts2 <- ts(d2, c(2015, 01), c(2016, 03), frequency = 12)
ts3 <- ts(d3, c(2015, 01), c(2016, 03), frequency = 12)

# prepare data for ggplot
dat <- ts.union(ts1, ts2, ts3)
dat <- melt(dat, id.vars = "x")

# add dates
dates <- seq(as.Date("2015-01-01"), as.Date("2016-03-01"), by = "months")
dat$Date <- dates

p <- ggplot(dat, aes(x = Date, y = value, col = Var2)) +
  geom_line(aes(linetype = Var2), size = 1) +
  geom_point(aes(shape = Var2), size = 2) +
  scale_linetype_manual(values = c(1, 1, 1)) +
  scale_shape_manual(values = c(0, 1, 2))
print(p)
tjebo
  • 21,977
  • 7
  • 58
  • 94
F. Brazil
  • 199
  • 1
  • 1
  • 10
  • Related https://stackoverflow.com/questions/29957669/different-colour-palettes-for-two-different-colour-aesthetic-mappings-in-ggplot2 – Tung Dec 22 '19 at 07:46
  • 1
    I modified the title - to make it more pertinent. Hope it helps to make it better visible for search engines and hope it better reflects what you want to achieve – tjebo Dec 22 '19 at 11:01

3 Answers3

4

To take @Rui Barradas's solution one step further, you can use guide_legend/override.aes() to modify the legends for the lines and points by giving the lines NA shape and the points NA linetypes.

my_color <- setNames(c("red", "blue", "green"),
                     c('ts1', 'ts2', 'ts3'))
ggplot(dat, aes(x = Date, y = value, colour = Var2)) +
  geom_line(data = subset(dat, Var2 != "ts3")) +
  geom_point(data = subset(dat, Var2 == "ts3")) +
  scale_color_manual("Legend", values = my_color) +
  guides(color = guide_legend(override.aes = list(linetype = c(1,   1, NA),
                                                  shape    = c(NA, NA, 19)))) +
  theme_classic(base_size = 14)

Created on 2019-12-22 by the reprex package (v0.3.0)

Tung
  • 26,371
  • 7
  • 91
  • 115
  • 2
    That's very nice. I still cannot get rid of the feeling that this question must be a dupe ... – tjebo Dec 22 '19 at 17:19
3

In such cases it seems keeping data in wide format is beneficial.

tidyr::pivot_wider(dat, names_from = Var2, values_from = value) %>%
     ggplot() +
     geom_line(aes(Date, ts1, color = 'ts1')) + 
     geom_line(aes(Date, ts2, color = 'ts2')) + 
     geom_point(aes(Date, ts3, color = 'ts3'))

enter image description here

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
3

It is possible to keep the data in long format as long as the data argument to the two geom_ layers subsets the full data set. This will automatically create a legend with all the colors.

ggplot(dat, aes(x = Date, y = value, colour = Var2)) +
  geom_line(data = subset(dat, Var2 != "ts3")) +
  geom_point(data = subset(dat, Var2 == "ts3")) +
  scale_color_manual(values = c("red", "blue", "green"))

enter image description here

Rui Barradas
  • 70,273
  • 8
  • 34
  • 66