Beginner in task automation, I would like to dynamically generate nested facet_wraps for many analytes. I know this is possible using purrr::map, but the problem is that my variables in the facet_wrap2 function are not constant. In other words, the variables defining the number of columns (qc: different levels of quality controls) and rows (site: different laboratories where measurements are performed) vary depending on the analyte.
Naively, I grouped by analytes and created two new columns, nqc (number of distinct QC levels per analyte) and nsite (number of distinct sites per analyte), hoping to dynamically map these variables. Unfortunately, the ncol and nrow arguments of facet_wrap2 require integers or NULL values, not vectors ("Error in map(): (...) Caused by error in facet_wrap(): ! nrow must be a whole number or NULL, not an integer vector").
Examples of 3 analytes (see data df0 below):
Analyte AAA :
df0: 2 qc measured in 1 site, thus the desired facet_wrap plot should have 2 rows and 1 column
Analyte BBB:
df0: 3 qc measured in 3 sites, thus the current facet_wrap plot is ok (3 rows and 3 columns)
Analyte CCC:
df0: 4 qc measured in 2 site, thus the desired facet_wrap plot should have 4 rows and 2 columns
I can't find a similar case, at least not one that's explicitly solved. Is this possible using purrr::map, lapply or others?
Thanks
Example plot of analyte AAA: Unwanted graph (left) and desired graph (right)

Code (unsuccessful attempt):
library(tidyverse)
library(ggh4x)
library(scales)
# mutate numbers of qc and site (perhaps unnecessary)
df0 <-
df0 |>
group_by(analyte) |>
mutate(
nsite = n_distinct(site),
nqc = n_distinct(qc)) |>
ungroup()
# list plots
list_plot <- df0 |>
group_split(analyte) |>
map(~ggplot(., aes(x = year_month, y = cv, group = analyzer)) +
facet_wrap2(
vars(qc, site),
# nrow = df0$nqc, (error)
drop = FALSE,
scales = "free_y",
strip = strip_nested()
) +
scale_x_discrete(expand = expansion(mult = 0.05)) +
scale_y_continuous(breaks = breaks_pretty(n=4)) +
geom_line(linewidth = 1) +
theme(legend.position = "none")
)
# display each plot
list_plot[[1]]
list_plot[[2]]
list_plot[[3]]
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", "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", "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_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_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-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, 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,
-171L), class = c("tbl_df", "tbl", "data.frame"))
I may have misunderstood, but do you get your desired outcome if you use nrow = unique(.$nqc) instead of nrow = df0$nqc? E.g.
Libraries/data:
library(tidyverse)
library(ggh4x)
library(scales)
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", "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", "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_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_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-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, 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,
-171L), class = c("tbl_df", "tbl", "data.frame"))
Code:
# mutate numbers of qc and site
df0 <-
df0 |>
group_by(analyte) |>
mutate(
nsite = n_distinct(site),
nqc = n_distinct(qc)) |>
ungroup()
# list plots
list_plot <- df0 |>
group_split(analyte) |>
map(~ggplot(., aes(x = year_month, y = cv, group = analyzer)) +
facet_wrap2(
vars(qc, site),
nrow = unique(.$nqc),
drop = FALSE,
scales = "free_y",
strip = strip_nested()
) +
scale_x_discrete(expand = expansion(mult = 0.05)) +
scale_y_continuous(breaks = breaks_pretty(n=4)) +
geom_line(linewidth = 1) +
theme(legend.position = "none")
)
# display each plot
list_plot[[1]]

list_plot[[2]]

list_plot[[3]]

Created on 2026-01-02 with reprex v2.1.1