The dataframe df0 below includes the following variables:
site: 3 remote partner laboratories (fixed number),
analyte: biomarkers measured at one or more of these sites (3 analytes in this example but >100 in my real data),
qc: the quality controls on which the analytes are measured (from 2 to 4 qc levels depending on the analyte),
analyzer: the analyzers located at each site, of different types and in varying numbers depending on the site.
year_month: the months during which QCs were measured daily,
cv: the coefficients of variation, calculated monthly for each analyte, on each analyzer, and per site,
Question: Considering the facet_grid below, how to split the legend of the analyzers by site, in the given order of sites and in the order of the analyzers within each site, as shown on the (right) desired plot, while adding the names of sites on the left side?
Note: The objective is to select a given analyte, with the difficulty being that not all analytes are measured on all analyzers or at all sites, and that the number of QC levels can vary depending on the analyte (in the example, 2 QC levels for analyte AAA, 3 for BBB, and 4 levels for CCC).
Thanks for help
Initial (left) and desired (right) legends:
Initial plot code:
library(tidyverse)
library(scales)
library(ggh4x)
# select analyte
select_analyte <- "CCC"
# Combinations of facetting variables for nested panels (# https://stackoverflow.com/questions/77618900/how-to-implement-conditional-coloring-for-facet-nested-panels-in-r)
combos <- df0 |>
distinct(qc, site, analyte) |>
arrange(qc, site, analyte) |>
mutate(qc = as.character(qc)) |>
filter(analyte == select_analyte)
strip_background <-
strip_nested(
bleed = FALSE,
background_x =
elem_list_rect(
fill = c(
case_match(
unique(combos$qc),
"" ~ "grey70",
.default = "grey70"
),
case_match(
combos$site,
"" ~ "grey85",
.default = "grey85"
))))
# plot
df0 |>
filter(analyte == select_analyte) |>
ggplot(aes(x=year_month, y=cv, colour=analyzer, group=analyzer)) +
ggtitle(paste0(select_analyte)) +
facet_wrap2(
vars(qc, site), ncol = 3,
drop = FALSE,
strip = strip_background) +
scale_x_discrete(expand = expansion(mult = c(0.05, 0.05))) +
scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0, 0.1)), breaks = breaks_pretty()) +
geom_line(linewidth=1) +
labs(x = NULL, y = expression('cv')) +
theme(
plot.margin=unit(c(0.2, 0.8, 0.2, 0.5),"cm"), # trbl
plot.title = element_text(size = 16, face = "bold", vjust = 1),
plot.subtitle = element_text(size = 11, vjust = 1),
panel.background = element_rect(fill = "white"),
panel.grid.major = element_line(colour="grey80", linewidth = 0.3),
panel.border = element_rect(colour = "grey10", fill = NA, linewidth = 0.4),
strip.background = element_rect(color="black", linetype="solid"),
strip.text.x = element_text(size = 13, color = "black"),
strip.text.y = element_text(size = 13, color = "black", angle = -90),
axis.title.x = element_text(vjust = -0.5, size = 13),
axis.title.y = element_text(vjust = 4.8, size = 13),
axis.text.x = element_text(margin = margin(b = 0.1), hjust= 1.12, vjust = 1.05, colour="black", size = 10, angle=60),
axis.text.y = element_text(margin = margin(l = -5, r = 2.5), colour="black", size = 12),
legend.margin = margin(unit(-2,"cm")),
legend.title = element_blank(),
legend.position = "top",
legend.justification='left',
legend.text = element_text(size = 14)) +
guides(colour = guide_legend(
override.aes = list(linewidth=1.3, label = ""))) +
coord_cartesian(clip = "off")
Data:
df0 <-
structure(list(site = c("SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX", "SX",
"SX", "SX", "SX", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY",
"SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY",
"SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY",
"SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY", "SY",
"SY", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ",
"SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ",
"SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ",
"SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ",
"SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ",
"SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ", "SZ",
"SZ"), analyte = c("AAA", "AAA", "AAA", "AAA", "AAA", "AAA",
"AAA", "AAA", "AAA", "AAA", "AAA", "AAA", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB",
"BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB",
"BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "BBB", "BBB", "BBB",
"BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB",
"BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC", "CCC",
"BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB",
"BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB", "BBB"
), qc = c("QC_A1", "QC_A2", "QC_A1", "QC_A2", "QC_A1", "QC_A2",
"QC_A1", "QC_A2", "QC_A1", "QC_A2", "QC_A1", "QC_A2", "QC_C1",
"QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4",
"QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3",
"QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2",
"QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1",
"QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4",
"QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3",
"QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_B1", "QC_B2",
"QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_B1", "QC_B2", "QC_B3",
"QC_B1", "QC_B2", "QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_B1",
"QC_B2", "QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_B1", "QC_B2",
"QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_C1", "QC_C2", "QC_C3",
"QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2",
"QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1",
"QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4",
"QC_B1", "QC_B2", "QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_B1",
"QC_B2", "QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_B1", "QC_B2",
"QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_C1", "QC_C2", "QC_C3",
"QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2",
"QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1",
"QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4",
"QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3",
"QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1", "QC_C2",
"QC_C3", "QC_C4", "QC_C1", "QC_C2", "QC_C3", "QC_C4", "QC_C1",
"QC_C2", "QC_C3", "QC_C4", "QC_B1", "QC_B2", "QC_B3", "QC_B1",
"QC_B2", "QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_B1", "QC_B2",
"QC_B3", "QC_B1", "QC_B2", "QC_B3", "QC_B1", "QC_B2", "QC_B3"
), analyzer = c("X1_C", "X1_C", "X3_C", "X3_C", "X1_C", "X1_C",
"X3_C", "X3_C", "X1_C", "X1_C", "X3_C", "X3_C", "X1_B1", "X1_B1",
"X1_B1", "X1_B1", "X1_B2", "X1_B2", "X1_B2", "X1_B2", "X2_B",
"X2_B", "X2_B", "X2_B", "X3_B", "X3_B", "X3_B", "X3_B", "X1_B1",
"X1_B1", "X1_B1", "X1_B1", "X1_B2", "X1_B2", "X1_B2", "X1_B2",
"X2_B", "X2_B", "X2_B", "X2_B", "X3_B", "X3_B", "X3_B", "X3_B",
"X1_B1", "X1_B1", "X1_B1", "X1_B1", "X1_B2", "X1_B2", "X1_B2",
"X1_B2", "X2_B", "X2_B", "X2_B", "X2_B", "X3_B", "X3_B", "X3_B",
"X3_B", "X1_C", "X1_C", "X1_C", "X2_C", "X2_C", "X2_C", "X3_C",
"X3_C", "X3_C", "X1_C", "X1_C", "X1_C", "X2_C", "X2_C", "X2_C",
"X3_C", "X3_C", "X3_C", "X1_C", "X1_C", "X1_C", "X2_C", "X2_C",
"X2_C", "X3_C", "X3_C", "X3_C", "Y1_B", "Y1_B", "Y1_B", "Y1_B",
"Y2_B", "Y2_B", "Y2_B", "Y2_B", "Y1_B", "Y1_B", "Y1_B", "Y1_B",
"Y2_B", "Y2_B", "Y2_B", "Y2_B", "Y1_B", "Y1_B", "Y1_B", "Y1_B",
"Y2_B", "Y2_B", "Y2_B", "Y2_B", "Y1_C", "Y1_C", "Y1_C", "Y2_C",
"Y2_C", "Y2_C", "Y1_C", "Y1_C", "Y1_C", "Y2_C", "Y2_C", "Y2_C",
"Y1_C", "Y1_C", "Y1_C", "Y2_C", "Y2_C", "Y2_C", "Z1_B1", "Z1_B1",
"Z1_B1", "Z1_B1", "Z1_B2", "Z1_B2", "Z1_B2", "Z1_B2", "Z2_B1",
"Z2_B1", "Z2_B1", "Z2_B1", "Z2_B2", "Z2_B2", "Z2_B2", "Z2_B2",
"Z1_B1", "Z1_B1", "Z1_B1", "Z1_B1", "Z1_B2", "Z1_B2", "Z1_B2",
"Z1_B2", "Z2_B1", "Z2_B1", "Z2_B1", "Z2_B1", "Z2_B2", "Z2_B2",
"Z2_B2", "Z2_B2", "Z1_B1", "Z1_B1", "Z1_B1", "Z1_B1", "Z1_B2",
"Z1_B2", "Z1_B2", "Z1_B2", "Z2_B1", "Z2_B1", "Z2_B1", "Z2_B1",
"Z2_B2", "Z2_B2", "Z2_B2", "Z2_B2", "Z1_C", "Z1_C", "Z1_C", "Z2_C",
"Z2_C", "Z2_C", "Z1_C", "Z1_C", "Z1_C", "Z2_C", "Z2_C", "Z2_C",
"Z1_C", "Z1_C", "Z1_C", "Z2_C", "Z2_C", "Z2_C"), year_month = c("2025-09",
"2025-09", "2025-09", "2025-09", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-11", "2025-11", "2025-11", "2025-11", "2025-09",
"2025-09", "2025-09", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-09", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-11", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-11", "2025-11", "2025-11", "2025-09",
"2025-09", "2025-09", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-10", "2025-10", "2025-10", "2025-11",
"2025-11", "2025-11", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-09", "2025-09", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-11", "2025-11", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-10", "2025-10", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-10", "2025-10", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11", "2025-09", "2025-09", "2025-09", "2025-09",
"2025-09", "2025-09", "2025-10", "2025-10", "2025-10", "2025-10",
"2025-10", "2025-10", "2025-11", "2025-11", "2025-11", "2025-11",
"2025-11", "2025-11"), cv = c(2.64, 3.83, 2.66, 3.11, 1.63, 1.82,
3.74, 3.81, 1.46, 2.07, 3.78, 3.17, 1.27, 1.05, 1.82, 2.84, 1.12,
0.97, 1.36, 2.81, 1.16, 2.51, 1.66, 3.24, 1.03, 0.78, 1.11, 2.92,
1.82, 0.87, 1.46, 2.56, 1.61, 1.24, 1.3, 2.45, 1.68, 1.69, 1.33,
2.24, 2.11, 0.74, 1.38, 2.33, 1.14, 0.96, 1.23, 3.05, 1.34, 1.01,
1.09, 2.35, 1.35, 1.06, 1.08, 2.2, 2.22, 0.68, 1.09, 2.56, 3.92,
2.66, 2.59, 2.38, 2.83, 1.95, 2.26, 1.58, 1.68, 2.59, 1.61, 1.56,
5.78, 2.05, 1.87, 3.68, 3.65, 1.21, 4.99, 1.23, 1.02, 2.63, 1.79,
1.13, 2.21, 1.22, 1.37, 1.05, 1.17, 1.05, 4.82, 1.88, 1.07, 1.17,
4.59, 2.64, 1.55, 1.87, 4.17, 1.87, 1.33, 1.38, 4.74, 1.51, 1.32,
1.29, 4.05, 1.78, 1.73, 1.43, 3.86, 4.99, 4.02, 4.12, 3.09, 1.32,
1.39, 4.52, 2.11, 2.97, 5.48, 2.31, 2.85, 2.89, 1.41, 1.31, 2.79,
1.49, 1.51, 1.35, 1.37, 1.48, 2.91, 1.21, 1.25, 1.25, 2.93, 1.31,
1.55, 1.41, 3.19, 1.34, 4.05, 1.36, 2.64, 1.24, 1.46, 1.42, 2.82,
1.78, 1.41, 1.52, 3.01, 2.24, 1.37, 1.84, 3.95, 1.53, 1.21, 1.21,
3.76, 2.49, 1.55, 1.26, 2.93, 2.39, 1.56, 1.26, 2.52, 2.06, 0.94,
1.19, 2.25, 1.73, 1.02, 1.31, 2.72, 2.24, 1.08, 2.09, 5.57, 3.65,
3.56, 3.19, 2.45, 2.14, 3.2, 1.8, 2.13, 2.56, 1.23, 1.21, 2.62,
1.44, 1.37)), row.names = c(NA, -195L), class = c("tbl_df", "tbl",
"data.frame"))
As suggested by @r2evans in the comments, the legendry package now offers an easy out-of-the-box option to
keep groups in blocks with their own titles
library(tidyverse)
library(scales)
library(ggh4x)
library(legendry)
df0 |>
filter(analyte == select_analyte) |>
ggplot(aes(x = year_month, y = cv, group = analyzer)) +
ggtitle(paste0(select_analyte)) +
facet_wrap2(
vars(qc, site),
ncol = 3,
drop = FALSE,
strip = strip_background
) +
scale_x_discrete(expand = expansion(mult = 0.05)) +
scale_y_continuous(
limits = c(0, NA),
expand = expansion(mult = c(0, 0.1)),
breaks = breaks_pretty()
) +
geom_line(
# Add the subgroup name and the seperator = "." used to split into
# groups
aes(color = paste0(site, ":.", analyzer)),
linewidth = 1
) +
labs(x = NULL, y = expression("cv")) +
theme(
plot.margin = unit(c(0.2, 0.8, 0.2, 0.5), "cm"), # trbl
plot.title = element_text(size = 16, face = "bold", vjust = 1),
plot.subtitle = element_text(size = 11, vjust = 1),
panel.background = element_rect(fill = "white"),
panel.grid.major = element_line(colour = "grey80", linewidth = 0.3),
panel.border = element_rect(colour = "grey10", fill = NA, linewidth = 0.4),
strip.background = element_rect(color = "black", linetype = "solid"),
strip.text.x = element_text(size = 13, color = "black"),
strip.text.y = element_text(size = 13, color = "black", angle = -90),
axis.title.x = element_text(vjust = -0.5, size = 13),
axis.title.y = element_text(vjust = 4.8, size = 13),
axis.text.x = element_text(
margin = margin(b = 0.1),
hjust = 1.12, vjust = 1.05, colour = "black", size = 10, angle = 60
),
axis.text.y = element_text(
margin = margin(l = -5, r = 2.5),
colour = "black", size = 12
),
legend.margin = margin(),
legend.position = "top",
legend.justification = "left",
legend.text = element_text(size = 14),
legend.direction = "vertical"
) +
coord_cartesian(clip = "off") +
guides(colour = guide_legend_group(
key = key_group_split(sep = "\\."),
override.aes = list(linewidth = 1.3),
nrow = 1,
title = NULL
)) +
theme(
legendry.legend.subtitle.position = "left",
legendry.group.spacing = unit(0, "cm")
)
A second option would be the ggnewscale package which however requires much more effort and as downside does not align the legend keys in columns across the legend groups:
library(tidyverse)
library(scales)
library(ggh4x)
library(ggnewscale)
df1 <- df0 |>
filter(analyte == select_analyte)
# per site color palettes
pal_color <- df1 |>
distinct(site, analyzer) |>
arrange(site, analyzer) |>
mutate(
color = scales::pal_hue()(n_distinct(analyzer))
) |>
split(~site) |>
lapply(
function(x) {
x |>
select(-site) |>
deframe()
}
)
# plot
df1 |>
ggplot(aes(x = year_month, y = cv, group = analyzer)) +
ggtitle(paste0(select_analyte)) +
facet_wrap2(
vars(qc, site),
ncol = 3,
drop = FALSE,
strip = strip_background
) +
scale_x_discrete(expand = expansion(mult = 0.05)) +
scale_y_continuous(
limits = c(0, NA),
expand = expansion(mult = c(0, 0.1)),
breaks = breaks_pretty()
) +
purrr::imap(
df1 |> split(~site),
function(x, site) {
list(
geom_line(data = x, aes(color = analyzer), linewidth = 1),
scale_color_manual(
values = pal_color[[site]],
guide = guide_legend(
title = paste0(site, ":"),
override.aes = list(linewidth = 1.3),
order = which(names(pal_color) == site)
)
),
ggnewscale::new_scale_color()
)
}
) +
labs(x = NULL, y = expression("cv")) +
theme(
plot.margin = unit(c(0.2, 0.8, 0.2, 0.5), "cm"), # trbl
plot.title = element_text(size = 16, face = "bold", vjust = 1),
plot.subtitle = element_text(size = 11, vjust = 1),
panel.background = element_rect(fill = "white"),
panel.grid.major = element_line(colour = "grey80", linewidth = 0.3),
panel.border = element_rect(colour = "grey10", fill = NA, linewidth = 0.4),
strip.background = element_rect(color = "black", linetype = "solid"),
strip.text.x = element_text(size = 13, color = "black"),
strip.text.y = element_text(size = 13, color = "black", angle = -90),
axis.title.x = element_text(vjust = -0.5, size = 13),
axis.title.y = element_text(vjust = 4.8, size = 13),
axis.text.x = element_text(
margin = margin(b = 0.1),
hjust = 1.12, vjust = 1.05, colour = "black", size = 10, angle = 60
),
axis.text.y = element_text(
margin = margin(l = -5, r = 2.5),
colour = "black", size = 12
),
legend.margin = margin(),
legend.position = "top",
legend.justification = "left",
legend.text = element_text(size = 14),
legend.box = "vertical",
legend.box.just = "left",
legend.spacing = unit(0, "pt")
) +
coord_cartesian(clip = "off")