Reputation: 1692
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.
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)
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.
Upvotes: 1
Views: 624
Reputation: 78927
Alternative:
Using strip.position = "bottom"
in facet_wrap
library(tidyverse)
library(lubridate)
df3 %>%
mutate(Month = month(date, label=TRUE, abbr=TRUE),
Year = year(date)) %>%
arrange(Year) %>%
ggplot(aes(x = Month, 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 = "") +
coord_cartesian(clip = 'off', ylim = c(0, 100)) +
facet_wrap(~Year, scales = "free_x", strip.position = "bottom") +
theme(strip.background = element_blank(),
strip.placement = "outside") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
Upvotes: 1
Reputation: 5722
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)
Upvotes: 1