So the idea is simple, and I guess the solution lies somewhere, but I just cannot find it. I have 3 yearly time series, with daily values, and I'd like to be able to display all 3 years in the same graph, where the x coordinates are the months, and the y coordinates the values for each year.
-
basic plot or ggplot? – D.J Sep 07 '20 at 14:07
-
any would do! I guess once I get the concept, I can look for it in other plotting tools – Philippe Grondier Sep 07 '20 at 14:22
-
Duplicates: [ggplot year by year comparison](https://stackoverflow.com/questions/13520639/ggplot-year-by-year-comparison); [plot data with different dates](https://stackoverflow.com/questions/17364435/plot-data-with-different-dates); [ggplot: Multiple years on same plot by month](https://stackoverflow.com/questions/41206181/ggplot-multiple-years-on-same-plot-by-month); [R - How to create a seasonal plot - Different lines for years](https://stackoverflow.com/questions/48722758/r-how-to-create-a-seasonal-plot-different-lines-for-years) – Henrik Sep 07 '20 at 14:37
3 Answers
I would suggest a ggplot2
approach to your consideration using dummy data. If you want months in x-axis you can 'hack' the date assigning a new year so that you can see the months in the axis after formating with scale_x_date()
. You also have to exatract the years from your date in order to add the colors. Here the code:
library(ggplot2)
library(dplyr)
set.seed(123)
#Dummy data
df <- data.frame(Date=c(seq(as.Date('2017-01-01'),
as.Date('2017-12-31'),
length.out = 365),
seq(as.Date('2018-01-01'),
as.Date('2018-12-31'),
length.out = 365),
seq(as.Date('2019-01-01'),
as.Date('2019-12-31'),
length.out = 365)),
value=rnorm(1095,5,2))
#Format
#Create months and years
df %>% mutate(Year=format(Date,'%Y'),
Date2=as.Date(paste0('2020-',format(Date,'%m-%d')))) %>%
ggplot(aes(x=Date2,y=value,group=Year,color=Year))+
geom_line()+
scale_x_date(date_labels="%B",breaks = '1 month')
Output:
Update: Also credits to great @AllanCameron, here a nicer solution using cumsum()
for the variable value
:
#Dummy data
df <- data.frame(Date=c(seq(as.Date('2017-01-01'),
as.Date('2017-12-31'),
length.out = 365),
seq(as.Date('2018-01-01'),
as.Date('2018-12-31'),
length.out = 365),
seq(as.Date('2019-01-01'),
as.Date('2019-12-31'),
length.out = 365)),
value = c(replicate(3, cumsum(rnorm(365)))))
#Format
#Create months and years
df %>% mutate(Year=format(Date,'%Y'),
Date2=as.Date(paste0('2020-',format(Date,'%m-%d')))) %>%
ggplot(aes(x=Date2,y=value,group=Year,color=Year))+
geom_line()+
scale_x_date(date_labels="%B",breaks = '1 month')
Output:

- 39,058
- 13
- 42
- 84
-
1I would have a very similar approach here Duck (+1), though for illustration you would get a nicer plot with `value = c(replicate(3, cumsum(rnorm(365))))` – Allan Cameron Sep 07 '20 at 14:23
-
@AllanCameron Dr. Cameron, you are right! I will update the solution with your helpful suggestion now ! – Duck Sep 07 '20 at 14:25
-
Thanks for all these interesting answers! So we are saying here that there is no "straight forward" way, and we have to create a fake and common time line to be able to superimpose multiple time series. – Philippe Grondier Sep 07 '20 at 14:40
-
@PhilippeGrondier not quite. You could use the `yday` function from lubridate to get the day of each year from 1:365, then use that as your x-axis. To get the months labelled correctly you would do `scale_x_continuous(breaks = c(1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335), labels = month.abb)` – Allan Cameron Sep 07 '20 at 14:45
-
@PhilippeGrondier It depends on your data! It is also possible to extract all day-month values from dates and plot in x-axis as factor! As AllanCameron said there are also other ways! – Duck Sep 07 '20 at 14:46
Here's an example using @Duck's data (with a different random seed) to show that it is possible to plot the three time series without faking the years, just plugging the dates and values into ggplot
and using a couple of lubridate
functions:
ggplot(df, aes(x = lubridate::yday(Date),
y = value,
color = factor(lubridate::year(Date)))) +
geom_line() +
scale_x_continuous(
breaks = lubridate::yday(seq(as.Date("2017-01-01"),
by = "1 month", length.out = 12)),
labels = month.abb) +
labs(x = "Date", colour = "Year")

- 147,086
- 7
- 49
- 87
in a regular plot it would look something like this:
#x11() # opens a graphics window
plot(mtcars$drat, type="l")
lines(mtcars$wt, col=2) # permits extra lines to be added to an already existing plot
points(mtcars$gear, col=3) # permits points added to an already existing plot
although if you have a dedicated time variable it would change like so:
x11()
plot(mtcars$date, mtcars$drat, type="l")
lines(mtcars$date, mtcars$wt, col=2)
lines(mtcars$date, mtcars$gear, col=3)
as mtcars doesn't have a timeline, this is not a valid example but the idea behind it works

- 1,180
- 1
- 8
- 17
-
Here you are just superimposing two time series with the same dates. My issue is with the superimposition of two time series relating to different years: I have a 2018, 2019 and 2020 series, and I want to display the 3 of them on one "Jan to Dec" x-axis – Philippe Grondier Sep 07 '20 at 14:25
-
ah, i see. i thought it would work as there shouldn't be a difference between years except for leap-years like 2020. i think you would still be able to do this while changing the date in the lines()/points() command - i have not tried that though. still i think @Duck 's answer is much better and more comprehensive so admittedly i'd go with that. i just wanted to give a non-ggplot answer as it can be faster for prototyping plots – D.J Sep 07 '20 at 14:36