Here is an example of how to create multi-level axis labels in an R plot using ggplot2. You can separate them into 2 levels on a plot x-axis or more. It depends on the situation.
I will visualize part of the AirPassengers dataset.
plot(AirPassengers)

Here is a sample of the last 36 months with month names and quarters.
require(lubridate)
df <- data.frame(Year = as.numeric(trunc(time(AirPassengers))),
Month = month.abb[cycle(AirPassengers)],
AirPassengers = as.numeric(AirPassengers))
df$Month <- factor(df$Month, levels=unique(df$Month))
df$Quarter <- quarters(make_date(df$Year, df$Month, ))
df <- tail(df, n = 36)
head(df)
# Year Month AirPassengers Quarter
# 109 1958 Jan 340 Q1
# 110 1958 Feb 318 Q1
# 111 1958 Mar 362 Q1
# 112 1958 Apr 348 Q2
# 113 1958 May 363 Q2
# 114 1958 Jun 435 Q2To create a plot axis with labels in two levels, I will add two calculations in separate columns. Each of the columns contains the first appearance of the year or quarter. That is what will be on the axis.
require(dplyr)
df <- df %>%
mutate(
Q = ifelse(lag(Quarter) != Quarter |
is.na(lag(Quarter)), Quarter, ""),
Y = ifelse(lag(Year) != Year |
is.na(lag(Year)), Year, "")
)
head(df)
# Year Month AirPassengers Quarter Q Y
# 109 1958 Jan 340 Q1 Q1 1958
# 110 1958 Feb 318 Q1
# 111 1958 Mar 362 Q1
# 112 1958 Apr 348 Q2 Q2
# 113 1958 May 363 Q2
# 114 1958 Jun 435 Q2The main principle of the solution is that you can use custom x-axis labels that are separated with newline characters. You can use the same approach to split the ggplot2 title into multiple rows.
Multi-level axis labels in R
There are multiple ways to create multi-level axis labels in the R plot. In this case, the goal is achieved by using scale_x_discrete with custom labels that are separated by a new line character.
require(ggplot2) ggplot(df, aes( x = interaction(Month, Year), y = AirPassengers, group = 1 )) + geom_line(color = "cadetblue") + ylim(0, NA) + scale_x_discrete(labels = paste(df$Q , df$Y, sep = "\n")) + labs(x = "", y = "") + theme_minimal()

Let’s say you want to put the year in a different position. For example, in the middle of the month series. Here is how it’s done, by detection position in the middle.
dfY <- df %>% select(Month, Year) %>% group_by(Year) %>% filter(row_number() == ceiling(n() / 2)) %>% mutate(Y2 = Year) df <- left_join(df, dfY) df$Y2 <- ifelse(is.na(df$Y2), "", as.character(df$Y2)) head(df) # Year Month AirPassengers Quarter Q Y Y2 # 1 1958 Jan 340 Q1 Q1 1958 # 2 1958 Feb 318 Q1 # 3 1958 Mar 362 Q1 # 4 1958 Apr 348 Q2 Q2 # 5 1958 May 363 Q2 # 6 1958 Jun 435 Q2 1958
Here is how it looks as a result.
ggplot(df, aes( x = interaction(Month, Year), y = AirPassengers, group = 1 )) + geom_line(color = "cadetblue") + ylim(0, NA) + scale_x_discrete(labels = paste(df$Q , df$Y2, sep = "\n")) + labs(x = "", y = "") + theme_minimal() + theme(axis.title = element_blank())

If the space allows, you can show x-axis labels on three levels. Here is a little tweak for using multiple colors for labels. If the year is an odd number, it will appear in one color, otherwise in a different one.
df$AxisColor <- ifelse(df$Year %% 2 == 0, "gray50", "gray") head(df) # Year Month AirPassengers Quarter Q Y Y2 AxisColor # 1 1958 Jan 340 Q1 Q1 1958 gray50 # 2 1958 Feb 318 Q1 gray50 # 3 1958 Mar 362 Q1 gray50 # 4 1958 Apr 348 Q2 Q2 gray50 # 5 1958 May 363 Q2 gray50 # 6 1958 Jun 435 Q2 1958 gray50
As a result, it looks like this.
ggplot(df, aes(
x = interaction(Month, Year),
y = AirPassengers,
group = 1
)) +
geom_line(color = "cadetblue", linewidth = 1) +
ylim(0, NA) +
geom_vline(
xintercept = seq(1, length(df$Month), by = 3),
color = "lightgray",
linewidth = 0.75,
linetype = 3) +
scale_x_discrete(labels = paste(df$Month, df$Q , df$Y2, sep = "\n")) +
labs(x = "", y = "") +
theme_minimal()+
theme(axis.text.y = element_text(color = "gray50"),
axis.text.x = element_text(color = df$AxisColor),
axis.line.x = element_line(linewidth = 0.5, color = "lightgray"),
axis.ticks.x = element_line(linewidth = 0.5, color = df$AxisColor),
panel.grid = element_blank(),
axis.title = element_blank())
Please look at other visualizations in this blog made using R. For example, gradient line chart, glowing line chart, and gradient word cloud.
Leave a Reply