The dataframe df includes the following variables:
x and y: the coordinates of concentration y as a function of x,
bmk: the biomarkers for which the x and y coordinates are given,
qc: the quality control levels, the number of which varies according to bmk,
site: the 3 laboratories where these bmk are measured,
almin: the minimum acceptable limit of y concentration (specific to the bmk),
almax: the maximum acceptable limit of y concentration (specific to the bmk).
For a selected bmk (select_bmk), I can represent almin and almax using geom_line (horizontal lines in red dashes) using the code below:
library(ggplot2)
library(dplyr)
# select bmk
select_bmk <- "bmk3"
# ggplot
df |>
filter(bmk == select_bmk) |>
ggplot(aes(x=x, y=y)) +
geom_point() +
facet_grid(qc ~ site, scales = "free_y") +
geom_hline(aes(yintercept = almin, group = qc), linetype = "longdash", colour = "red3") +
geom_hline(aes(yintercept = almax, group = qc), linetype = "longdash", colour = "red3")
However, I would like to insert a space between the last column of facets and the strips to display the names of the limits (here, almin and almax) followed by their specific values (in parentheses), as in the simulation below.
Is this possible?
Note: In my real data, there are more than 120 different bmk (hence the need to select only one), which have from 1 to 4 different qc levels, and about 12 different acceptable limits, each with specific qc level values.
Data:
library(ggplot2)
library(dplyr)
set.seed(123)
# bmk1
x <- 3 + rnorm(75)
y <- 15 + rnorm(75)
bmk <- as.factor(c(rep("bmk1",75)))
qc <- as.factor(c(rep("L1",75)))
site <- as.factor(rep(c(rep("A",25), rep("B",25), rep("C",25)), 1))
almin <- c(rep(13.5,75))
almax <- c(rep(16.5,75))
df1 <- data.frame(x,y,bmk,qc,site,almin,almax)
# bmk2
x <- 3 + rnorm(150)
y <- 20 + rnorm(150)
bmk <- as.factor(c(rep("bmk2",150)))
qc <- as.factor(c(rep("L1",75), rep("L2",75)))
site <- as.factor(rep(c(rep("A",25), rep("B",25), rep("C",25)), 2))
almin <- c(rep(19,150))
almax <- c(rep(21,150))
df2 <- data.frame(x,y,bmk,qc,site,almin,almax)
df2 <- df2 |> mutate(y = case_when(qc=="L2"~y+10, TRUE~y),
almin = case_when(qc=="L2"~almin+10, TRUE~almin),
almax = case_when(qc=="L2"~almax+10, TRUE~almax))
# bmk3
x <- 3 + rnorm(90)
y <- 30 + rnorm(90)
bmk <- as.factor(c(rep("bmk3",90)))
qc <- as.factor(c(rep("L1",30), rep("L2",30), rep("L3",30)))
site <- as.factor(rep(c(rep("A",10), rep("B",10), rep("C",10)), 3))
almin <- c(rep(29,90))
almax <- c(rep(31,90))
df3 <- data.frame(x,y,bmk,qc,site,almin,almax)
df3 <- df3 |> mutate(y = case_when(qc=="L2"~y+10, qc=="L3"~y+20, TRUE~y),
almin = case_when(qc=="L2"~almin+10, qc=="L3"~almin+20, TRUE~almin),
almax = case_when(qc=="L2"~almax+10, qc=="L3"~almax+20, TRUE~almax))
# rbind
df <- rbind(df1, df2, df3)
df$x <- round(df$x,2)
df$y <- round(df$y,2)
Thanks for help
One possible option would be to add the labels via a secondary axis where I use gg4hx::facetted_pos_scales to set the labels individually for each row of the facet grid:
library(ggplot2)
library(dplyr, warn = FALSE)
library(ggh4x)
select_bmk <- "bmk3"
# Create a list of y scales per qc
scales_y <- df |>
filter(bmk == select_bmk) |>
distinct(
qc, almin, almax
) |>
split(~qc) |>
lapply(\(x) {
scale_y_continuous(
sec.axis = dup_axis(
breaks = c(x$almin, x$almax),
labels = paste0(
c("almin", "almax"), " (", c(x$almin, x$almax), ")"
)
)
)
})
df |>
filter(bmk == select_bmk) |>
ggplot(aes(x = x, y = y)) +
geom_point() +
facet_grid(qc ~ site, scales = "free_y") +
geom_hline(
aes(yintercept = almin, group = qc),
linetype = "longdash", colour = "red3"
) +
geom_hline(
aes(yintercept = almax, group = qc),
linetype = "longdash", colour = "red3"
) +
ggh4x::facetted_pos_scales(
y = scales_y
) +
theme(
strip.placement = "outside",
axis.ticks.y.right = element_blank(),
axis.text.y.right = element_text(
colour = "red3"
)
)