Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

In ggplot2, how can I display the month abbreviation on the x-axis vertically with the year below the months horizontally?

I would like the following time series to display the month abbreviation (e.g., Jan, Feb, etc.) in chronological order with a vertical orientation while also displaying the year horizontally below the months. Please see the ideal figure example below.

Example Data:

library(dplyr)
library(ggplot2)

df1 <- data.frame(matrix(ncol = 3, nrow = 12))
colnames(df1)[1:3] <- c("Date", "Group", "Value")
df1$Date <- rep(seq.Date(as.Date("2020-03-14"),as.Date("2020-08-20"),"1 month"),2)
df1$Group <- sort(rep(c("A","B"),6))
df1$Value <- rnorm(12,50,10)
df1 <- df1 %>%
  mutate(Month = month(Date),
         Year = year(Date),
         date = zoo::as.yearmon(paste(Year, Month), "%Y %m"))

df2 <- data.frame(matrix(ncol = 3, nrow = 12))
colnames(df2)[1:3] <- c("Date", "Group", "Value")
df2$Date <- rep(seq.Date(as.Date("2021-03-14"),as.Date("2021-08-20"),"1 month"),2)
df2$Group <- sort(rep(c("A","B"),6))
df2$Value <- rnorm(12,50,10)
df2 <- df2 %>%
  mutate(Month = month(Date),
         Year = year(Date),
         date = zoo::as.yearmon(paste(Year, Month), "%Y %m"))

df3 <- rbind(df1,df2)

Example Figure: This code produces the figure below with the year associated with each month, both vertically oriented.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

cols <- c("A" = "#ca0020", "B" = "#0571b0")

ggplot(data = df3, aes(x = factor(date), y = Value, color = Group, group = paste(Year,Group))) +
  geom_line() +
  geom_point(size = 3, aes(fill = Group), color = "black", shape = 21) +
  scale_fill_manual(values = cols) +
  scale_color_manual(values = cols) +
  labs(x = "") +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
        axis.text.y = element_text(size = 14, color = "black"),
        legend.title = element_blank(),
        legend.direction = "horizontal",
        legend.margin = margin(),
        legend.background = element_blank(),
        legend.position = c(0.1,0.93),
        panel.border = element_blank()) +
  guides(fill = guide_legend(nrow = 2)) +
  coord_cartesian(clip = 'off', ylim = c(0, 100)) +
  annotation_custom(grid::rectGrob(gp = grid::gpar(fill = NA))) +
  annotate('rect',
           xmin = 6.35,
           xmax = 6.65,
           ymin = -10, ymax = 0, fill = 'white') +
  annotate('segment',
           x = c(6.35, 6.65),
           xend = c(6.35, 6.65), y = -10, yend = 0)

enter image description here

Ideal Figure: The ideal figure would display the month vertically and the year horizontally (please see below). I’m pretty sure I can add the year horizontally based off this SO question, I am just having an issue with displaying the month without the year in chronological order.

I have tried using zoo::scale_x_yearmon(format = "%b") in the example figure code above but have not had success with this approach.

enter image description here

>Solution :

Here a solution partially based in Multi-row x-axis labels in ggplot line chart

ggplot(data = df3, aes(x = factor(date), y = Value, color = Group, group = paste(Year,Group))) +
  geom_line() +
  geom_point(size = 3, aes(fill = Group), color = "black", shape = 21) +
  scale_fill_manual(values = cols) +
  scale_color_manual(values = cols) +
  scale_x_discrete(labels=substr(df3$date,1,3))+
  labs(x = "") +
  theme_bw() +
  theme(plot.margin = unit(c(1, 1, 2, 1), "lines"),
        panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
        axis.text.y = element_text(size = 14, color = "black"),
        legend.title = element_blank(),
        legend.direction = "horizontal",
        legend.margin = margin(),
        legend.background = element_blank(),
        legend.position = c(0.1,0.93),
        panel.border = element_blank()) +
  guides(fill = guide_legend(nrow = 2)) +
  coord_cartesian(clip = 'off', ylim = c(0, 100)) +
  annotation_custom(grid::rectGrob(gp = grid::gpar(fill = NA))) +
    annotate(geom = "text", x = 3.5 + 6 * (0:1), y = -30, label = unique(df3$Year), size = 6) +
  annotate('rect',
           xmin = 6.35,
           xmax = 6.65,
           ymin = -10, ymax = 0, fill = 'white') +
  annotate('segment',
           x = c(6.35, 6.65),
           xend = c(6.35, 6.65), y = -10, yend = 0)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading