Home > Back-end >  Add grid lines every N months to geom_point plot with date as x-axis
Add grid lines every N months to geom_point plot with date as x-axis

Time:04-27

I have a dataframe, as given a sample below:

df <- data.frame(list(Name = c("A", "A", "A", "A", "A", 
                                     "B", "B", "B", "B", "B"), 
                            Date_Types = c("Date1", "Date2", 
                                     "Date3","Date4", "Date5", 
                                     "Date1", "Date2", "Date3", 
                                     "Date4", "Date5"), Dates = 
                              structure(c(18903, 18965, 19081, 
                                     19116, 19172, 19083, 19097, 
                                     19219, 19249, 19341), class = 
                                 "Date")))

I want to create a plot and add vertical grid lines every 3 months (so every quarter of the year). I have the following code:

library(ggplot2)
my_date_format <- function()
{
   function(x)
   {
       m <- format(x,"%b")
       y <- format(x,"%Y")
       ifelse(duplicated(y),m,paste(m,y))
   }
}

ggplot(df, aes(x = Dates, y = Name))   
  theme_classic()   geom_point(aes(shape = Date_Types), size = 8)  
  theme(axis.line.y = element_blank(), axis.ticks = element_blank(),
        axis.title = element_blank(), axis.text = element_text(size=22),
        legend.text = element_text(size=22), legend.title = element_blank())  
  scale_x_date(date_break = "1 month", labels = my_date_format())  
  geom_vline(aes(xintercept= as.Date("2022-05-01")), 
             linetype = "dashed", color = "black", size = 1)

enter image description here

This means vertical lines every January, April, July, and October. The desired output would look like this:

enter image description here

CodePudding user response:

One approach would be to add "grid lines" manually using geom_hline and a vector of dates where you want your grid lines. You could create the vector manually or compute the starting and final quarters dynamically using lubridate.

library(ggplot2)
library(lubridate)

min_date <- lubridate::floor_date(min(df$Dates), unit = "quarter")
max_date <- lubridate::ceiling_date(max(df$Dates), unit = "quarter")

quarters <- seq.Date(min_date, max_date, by = "quarter")

ggplot(df, aes(x = Dates, y = Name))  
  theme_classic()  
  geom_vline(xintercept = quarters, color = "grey92", size = .5)  
  geom_point(aes(shape = Date_Types), size = 8)  
  theme(
    axis.line.y = element_blank(), axis.ticks = element_blank(),
    axis.title = element_blank(), axis.text = element_text(size = 12),
    legend.text = element_text(size = 12), legend.title = element_blank()
  )  
  scale_x_date(date_break = "1 month", labels = my_date_format())  
  geom_vline(aes(xintercept = as.Date("2022-05-01")),
    linetype = "dashed", color = "black", size = 1
  )

CodePudding user response:

Using the lubridate package, create a quarterly sequence and add this as vertical lines to the plot:

library(lubridate)

...   
geom_vline(xintercept = seq(floor_date(min(df$Dates), unit = "quarter"),
                            ceiling_date(max(df$Dates), unit = "quarter"),
                            by = "1 quarter"))

Full code:

df <- data.frame(list(Name = c("A", "A", "A", "A", "A", 
                                     "B", "B", "B", "B", "B"), 
                            Date_Types = c("Date1", "Date2", 
                                     "Date3","Date4", "Date5", 
                                     "Date1", "Date2", "Date3", 
                                     "Date4", "Date5"), Dates = 
                              structure(c(18903, 18965, 19081, 
                                     19116, 19172, 19083, 19097, 
                                     19219, 19249, 19341), class = 
                                 "Date")))
library(ggplot2)
my_date_format <- function()
{
    function(x)
    {
        m <- format(x,"%b")
        y <- format(x,"%Y")
        ifelse(duplicated(y),m,paste(m,y))
    }
}
library(lubridate)
ggplot(df, aes(x = Dates, y = Name))   
geom_vline(xintercept = seq(floor_date(min(df$Dates), unit = "quarter"),
                            ceiling_date(max(df$Dates), unit = "quarter"),
                            by = "1 quarter"),
           color = "grey80")   
theme_classic()   geom_point(aes(shape = Date_Types), size = 8)  
theme(axis.line.y = element_blank(), axis.ticks = element_blank(),
      axis.title = element_blank(), axis.text = element_text(size=12),
      legend.text = element_text(size=22), legend.title = element_blank())  
scale_x_date(date_break = "1 month", labels = my_date_format())  
geom_vline(aes(xintercept= as.Date("2022-05-01")), 
           linetype = "dashed", color = "black", size = 1) 

enter image description here

CodePudding user response:

You can create a new data.frame with the dates (generated from your original data frame) and supply it to geom_vline like this:

quarters <- data.frame(
   q = seq.Date(as.Date(ISOdate(min(year(df$Dates)), 1, 1)),
                max(df$Dates),
                "3 months"))

ggplot(df, aes(x = Dates, y = Name))   
  theme_classic()   geom_point(aes(shape = Date_Types))  
  theme(axis.line.y = element_blank(), axis.ticks = element_blank(),
        axis.title = element_blank(), legend.title = element_blank())  
  scale_x_date(date_break = "1 month", labels = my_date_format())  
  geom_vline(aes(xintercept = q), data = quarters,
             linetype = "dashed", color = "black", size = 1)

Dates as Reference Lines

  • Related