Search code examples
rggplot2time-seriesmissing-data

How to plot missing dates in time series data using ggplot2?


I have a time series data of Temperature (average, maximum, minimum) with missing dates, and the line plot is not continue, this graph does a jump with a horizontal line until the next date. I would like that the line be continue.

My data set is the next

Fecha      -- T      Tmin Tmax

1. Fecha      ---------- T   --   Tmin Tmax
2. 2015-07-01   - 11,16 - 7,3 -  17 
3. 2015-07-02    - 11,49 -   8   - 17,1
4. 2015-07-03   - 11,2 -    8,8 -     15,8
5. 2015-07-04 - 11,20 - 8,6  - 16
6. 2015-07-05    -11,23 -   8,9  - 15,7
7. 2015-07-06    -10,40  - 7,7  -  15,4
8. 2015-07-07 - 10,10 - 8,1 -  14,8
9. 2015-07-08 - 10,04 - 7,3 -  15,4
10. 2018-01-01   - 11,08 -  4,9 -  17,8
11. 2018-01-02   -11,40 -   4,2 -  16,3
12. 2018-01-03 -    9,000 - 5,5  - 13,5
13. 2018-01-04  - 8,584  - 6    -  12,8
14. 2018-01-05  - 8,679  - 7,3  -  11,9
15. 2018-01-06 -    8,75 -  6,8 -  13
16. 2018-01-07   - 9,33 - 6,4    - 15,2
17. 2018-01-08  - 9,63 -    6,3 -  13,9

My code is:

setwd("C:/Users/2018/Documents/Belmira")
dir()
mmp1<-read.csv2("Temperatura.csv")
head(mmp1)
p<-as.Date(mmp1$Fecha)
mmp1$Fecha<-p
w<-ggplot() +
  geom_line(mapping = aes(x = mmp1$Fecha, y = mmp1$Tmin, colour="Min"), size=0.71) +
  geom_line(mapping = aes(x = mmp1$Fecha, y = mmp1$T, colour="P"), size=0.71) +
  geom_line(mapping = aes(x = mmp1$Fecha, y = mmp1$Tmax, colour="Max"), size=0.71) +
  ylim(c(1,18))+
  theme (text = element_text(size=11)) +
  ylab(expression("Temperatura (°C)"))+
  xlab(expression("Tiempo"))+
  scale_x_date(labels = date_format("%d/%m"))+
  theme(axis.text.x=element_text(angle=45, hjust=1))+
  scale_x_date(date_breaks = "30 day", date_labels = "%m-%y", limits = as.Date(c('2015-07-01','2019-01-01')), expand = (c(0.001,0.008)))+
  theme(plot.title = element_text(hjust = 0.5))+
  theme(panel.background = element_rect(fill = 'white', colour = 'white', size = 1.2, linetype = 7))+
  theme(text=element_text(family="arial", face="bold", size=12))+
  theme(axis.title.y = element_text(face="bold", family = "arial", vjust=1.5, colour="black", hjust = 0.5, size=rel(1.2)))+
  theme(axis.title.x = element_text(face="bold", family = "arial", vjust=0.5, colour="black", size=rel(1.2)))+
  theme(axis.text.x = element_text(family= "arial",face = "plain", colour="black", size=rel(1.1)))+
  theme(axis.text.y = element_text(family= "arial",face = "plain", colour="black", size=rel(1.1)))+
  theme(axis.line = element_line(size = 1, colour = "black"))+
  scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(-4,28), expand=c(0,0))+
  scale_colour_manual(name="Leyenda",
                      values=c(Min="green", P="#56B4E9", Max="Red"))+
  theme(legend.title = element_text(colour="black", size=12, face="bold", family = "arial"))+
  theme(legend.key = element_rect(fill = "white"))+
  guides(colour=guide_legend(order = 2),
         shape=guide_legend(order = 2))
w

the result is:


Solution

  • If I got you right you want the gaps in your data not show up as "a long horizontal" line? This is no simple task. Perhaps the prefered and simplest solution would be to use facetting, e.g. by year. If you insist on having all the data in one plot then you have to try a hacky approach, by getting rid of the date-axis and setting the labels manually. Have a look at the different approaches:

    df <- read.table(text="
        Fecha - T - Tmin - Tmax
        2015-07-01 - 11,16 - 7,3 - 17
        2015-07-02 - 11,49 - 8 - 17,1
        2015-07-03 - 11,2 - 8,8 - 15,8
        2015-07-04 - 11,20 - 8,6 - 16
        2015-07-05 - 11,23 - 8,9 - 15,7
        2015-07-06 - 10,40 - 7,7 - 15,4
        2015-07-07 - 10,10 - 8,1 - 14,8
        2015-07-08 - 10,04 - 7,3 - 15,4
        2018-01-01 - 11,08 - 4,9 - 17,8
        2018-01-02 - 11,40 - 4,2 - 16,3
        2018-01-03 - 9,000 - 5,5 - 13,5
        2018-01-04 - 8,584 - 6 - 12,8
        2018-01-05 - 8,679 - 7,3 - 11,9
        2018-01-06 - 8,75 - 6,8 - 13
        2018-01-07 - 9,33 - 6,4 - 15,2
        2018-01-08 - 9,63 - 6,3 - 13,9
    ", header = TRUE, dec = ",")
    
    mmp1 <- df[,!grepl("^X", names(df))]
    mmp1$Fecha <- as.Date(mmp1$Fecha)
    
    library(ggplot2)
    library(scales)
    library(dplyr)
    library(tibble)
    
    mmp2 <- mmp1 %>% 
      mutate(
        year_fecha = as.character(lubridate::year(Fecha)),
        Fecha2 = format(Fecha, "%d-%m"),
        Fecha2 = forcats::fct_reorder(Fecha2, Fecha)) %>% 
      arrange(Fecha) %>% 
      rowid_to_column(var = "Fecha3")
    
    # Put the theme code aside
    polish <- theme(text = element_text(size=11)) +
      theme(axis.text.x=element_text(angle=45, hjust=1))+
      theme(plot.title = element_text(hjust = 0.5))+
      theme(panel.background = element_rect(fill = 'white', colour = 'white', size = 1.2, linetype = 7))+
      theme(text=element_text(family="arial", face="bold", size=12))+
      theme(axis.title.y = element_text(face="bold", family = "arial", vjust=1.5, colour="black", hjust = 0.5, size=rel(1.2)))+
      theme(axis.title.x = element_text(face="bold", family = "arial", vjust=0.5, colour="black", size=rel(1.2)))+
      theme(axis.text.x = element_text(family= "sans",face = "plain", colour="black", size=rel(1.1)))+
      theme(axis.text.y = element_text(family= "sans",face = "plain", colour="black", size=rel(1.1)))+
      theme(axis.line = element_line(size = 1, colour = "black"))+
      theme(legend.title = element_text(colour="black", size=12, face="bold", family = "arial"))+
      theme(legend.key = element_rect(fill = "white"))
    
    # Simple and prefered solution: Facet by e.g. by year
    w1 <- ggplot(data = mmp2) +
      geom_line(mapping = aes(x = Fecha, y = Tmin, colour="Min"), size=0.71) +
      geom_line(mapping = aes(x = Fecha, y = T, colour="P"), size=0.71) +
      geom_line(mapping = aes(x = Fecha, y = Tmax, colour="Max"), size=0.71) +
      scale_x_date(date_breaks = "1 day", date_labels = "%d-%m", expand = (c(0.001,0.008)))+
      scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(1,18), expand=c(0,0)) +
      scale_colour_manual(name="Leyenda",
                          values=c(Min="green", P="#56B4E9", Max="Red")) +
      ylab("Temperatura (C)")+
      xlab("Tiempo") +
      guides(colour=guide_legend(order = 2),
             shape=guide_legend(order = 2)) +
      facet_wrap(~year_fecha, scales = "free_x") +
      polish
    
    w1  
    

    # Hacky solutions with some manual labelling
    labs <- select(mmp2, Fecha3, Fecha2) %>% 
      tibble::deframe()
    
    date_lab <- function(x) {
      labs[as.character(x)]
    }
    
    # Draw the data as one continuous line
    w2 <- ggplot(data = mmp2) +
      geom_line(mapping = aes(x = Fecha3, y = Tmin, colour="Min"), size=0.71) +
      geom_line(mapping = aes(x = Fecha3, y = T, colour="P"), size=0.71) +
      geom_line(mapping = aes(x = Fecha3, y = Tmax, colour="Max"), size=0.71) +
      scale_x_continuous(breaks = as.integer(names(labs)), labels = date_lab, expand = (c(0.001,0.008))) +
      scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(1,18), expand=c(0,0)) +
      scale_colour_manual(name="Leyenda",
                          values=c(Min="green", P="#56B4E9", Max="Red")) +
      ylab("Temperatura (C)")+
      xlab("Tiempo") +
      guides(colour=guide_legend(order = 2),
             shape=guide_legend(order = 2)) +
      polish
    w2
    

    # Separate lines for years by using different linetypes 
    w3 <- ggplot(data = mmp2) +
      geom_line(mapping = aes(x = Fecha3, y = Tmin, colour="Min", linetype = year_fecha), size=0.71) +
      geom_line(mapping = aes(x = Fecha3, y = T, colour="P", linetype = year_fecha), size=0.71) +
      geom_line(mapping = aes(x = Fecha3, y = Tmax, colour="Max", linetype = year_fecha), size=0.71) +
      scale_x_continuous(breaks = as.integer(names(labs)), labels = date_lab, expand = (c(0.001,0.008))) +
      scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(1,18), expand=c(0,0)) +
      scale_colour_manual(name="Leyenda",
                          values=c(Min="green", P="#56B4E9", Max="Red")) +
      ylab("Temperatura (C)")+
      xlab("Tiempo") +
      guides(colour=guide_legend(order = 2),
             shape=guide_legend(order = 2)) +
      polish
    w3
    

    Created on 2020-03-28 by the reprex package (v0.3.0)