I have multi-row x-axis labels such that the first row is month and the second row is year. However, I run into check_aesthetics()
errors when I try to use the multi-row axis labels with facet_wrap()
.
Example Data:
library(data.table)
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)
cols <- c("A" = "#ca0020", "B" = "#0571b0")
Figure without facet_wrap()
showing the multi-row x-axis
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 = c(3.5,9.5), y = -15, 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)
Now when I try to add the facet_wrap()
...
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 = c(3.5,9.5), y = -15, 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)
facet_wrap(~Group)
...it throws the error Error in `check_aesthetics()`: ! Aesthetics must be either length 1 or the same as the data (4): label
.
The error resides within annotate(geom = "text", x = c(3.5,9.5), y = -15, label = unique(df3$Year), size = 6)
but I can't figure out how to fix it. I have tried changing the label =
and the x =
but no luck. The ideal figure would have two plots, each with multi-row x-axis labels where, similar to the example figure above, the top row is month and the second row is year. Any thoughts on how to achieve this?
CodePudding user response:
One kind of hacky way to do this is to just make two text annotations
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 = c(3.5), y = -15, label = 2020, size = 6)
annotate(geom = "text", x = c(9.5), y = -15, label = 2021, 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)
facet_wrap(~Group)
CodePudding user response:
If you don't mind moving the year value to the strip you could use ggh4x
package.
library(dplyr)
library(ggplot2)
library(lubridate)
library(ggh4x)
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 = NULL)
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.90),
panel.border = element_blank())
guides(fill = guide_legend(nrow = 2))
coord_cartesian(clip = 'off', ylim = c(0, 100))
facet_nested(~Group Year, scales = "free_x")
Created on 2022-10-12 with reprex v2.0.2