Teicoplanin (Chen 2023)
Source:vignettes/articles/Chen_2023_teicoplanin.Rmd
Chen_2023_teicoplanin.RmdModel and source
mod_meta <- nlmixr2est::nlmixr(readModelDb("Chen_2023_teicoplanin"))$meta
#> ℹ parameter labels from comments will be replaced by 'label()'- Citation: Chen CY, Xie M, Gong J, Yu N, Wei R, Lei LL, Zhao SM, Li RM, Dong X, Zhang XL, Zhou Y, Li SL, Cui YM. Population pharmacokinetic analysis and dosing regimen optimization of teicoplanin in critically ill patients with sepsis. Front Pharmacol. 2023;14:1132367. doi:10.3389/fphar.2023.1132367
- Description: Two-compartment IV infusion population PK model for teicoplanin in critically ill adults with sepsis in the intensive care unit, with CKD-EPI estimated glomerular filtration rate as a power covariate on clearance (Chen 2023)
- Article (DOI): https://doi.org/10.3389/fphar.2023.1132367
This vignette validates the packaged
Chen_2023_teicoplanin model – a two-compartment IV infusion
population PK model for teicoplanin developed from 249 serum
concentrations in 59 critically ill adults with sepsis in a Beijing ICU
(Chen 2023). The final model carries a single covariate: the
BSA-normalized CKD-EPI estimated glomerular filtration rate as a power
term on clearance.
The paper’s quantitative deliverable is its Monte Carlo dosing-optimization analysis (Table 3, Figures 3-5), which reports median trough concentrations at 72 h and 240 h and the 24-h AUC/MIC ratio for thirteen candidate regimens across five renal-function strata. Those simulations are an unusually strong validation target because they are pure forward predictions of the packaged model, so this vignette reproduces them directly and compares against the published numbers.
Population
The Chen 2023 cohort comprised 59 adults (37 male, 22 female) admitted to the ICU of Peking University First Hospital with sepsis diagnosed by the Sepsis-3.0 criteria, with confirmed or suspected gram-positive coccal infection and an expected teicoplanin course of at least 4 days. Median age was 72.0 years (range 28.0-92.0) and median weight 65.0 kg (range 35.0-90.0). Renal function spanned the full clinical range: median CKD-EPI GFR 71.9 mL/min/1.73 m^2 (range 11.0-124), with 23.7% of subjects at GFR >= 90, 33.9% at 60-90, 23.7% at 30-60, 8.5% at 15-30 and 10.2% below 15 mL/min/1.73 m^2. Patients receiving renal replacement therapy were excluded by protocol, as were pregnant and lactating patients and those with endocardial, bone or joint infections.
Teicoplanin was infused over 30-60 min at 400 mg q12h for 3 doses followed by 400 mg once daily. Four trough samples were drawn from every patient (immediately before the 3rd, 4th, 5th and 6th doses); each patient contributed one additional sample assigned by thirds (immediately after the 5th infusion, 1 h after the 5th dose, or 1 h before the 6th dose). Assay: HPLC-UV at 240 nm, LOQ 3.125 ug/mL, linear to 100 ug/mL. Baseline demographics and laboratory values are tabulated in Chen 2023 Table 1.
The same information is available programmatically via the model’s
population metadata:
str(mod_meta$population)
#> List of 16
#> $ species : chr "human"
#> $ n_subjects : int 59
#> $ n_studies : int 1
#> $ age_range : chr "28.0-92.0 years (Chen 2023 Table 1)"
#> $ age_median : chr "72.0 years"
#> $ weight_range : chr "35.0-90.0 kg (Chen 2023 Table 1)"
#> $ weight_median : chr "65.0 kg"
#> $ sex_female_pct : num 37.3
#> $ race_ethnicity : chr "Not reported by category; single-centre Chinese ICU cohort described in the Conclusion as a 'prospective cohort"| __truncated__
#> $ disease_state : chr "Critically ill adults (age >= 18 years) admitted to the intensive care unit with sepsis diagnosed by the Sepsis"| __truncated__
#> $ dose_range : chr "Teicoplanin 400 mg IV infusion every 12 h for 3 doses (loading), followed by 400 mg once daily, with subsequent"| __truncated__
#> $ regions : chr "China (Peking University First Hospital ICU, Beijing)"
#> $ renal_function : chr "GFR (CKD-EPI) median 71.9 mL/min/1.73 m^2, range 11.0-124 (Chen 2023 Table 1). Serum creatinine median 80.3 umo"| __truncated__
#> $ hepatic_function : chr "ALT median 15.0 IU/L (range 4.00-993), AST median 26.0 IU/L (range 11.0-2390), total bilirubin median 18.7 umol"| __truncated__
#> $ screened_covariates: chr "Tested-but-not-retained covariates (Chen 2023 Methods 2.4 and Results 3.2): sex, age, height, weight, BMI, ALT,"| __truncated__
#> $ notes : chr "Prospective open-label PPK study; 249 serum concentrations from 59 subjects (22 female, 37 male). Sampling: tro"| __truncated__Source trace
The per-parameter origin is recorded as an in-file comment next to
each ini() entry in
inst/modeldb/specificDrugs/Chen_2023_teicoplanin.R. The
table below collects them in one place. All fixed- and random-effect
values come from Chen 2023 Table 2 (“Parameter estimates, standard
error, and bootstrap confidence intervals of the final model”); the
structural equations come from the printed final-model equations 5-9 in
Results section 3.2.
| Parameter / equation | Value | Source location |
|---|---|---|
lcl (typical CL) |
log(1.03) |
Table 2 PK Parameter row CL (L/h) = 1.03 (RSE 16.6%); Eq. 6 |
lvc (typical V1) |
log(20.1) |
Table 2 PK Parameter row V1 (L) = 20.1 (RSE 12.9%); Eq. 7 |
lq (typical Q) |
log(3.12) |
Table 2 PK Parameter row Q (L/h) = 3.12 (RSE 10.9%); Eq. 8 |
lvp (typical V2) |
log(101) |
Table 2 PK Parameter row V2 (L) = 101 (RSE 12.7%); Eq. 9 |
e_crcl_cl (power exponent on GFR) |
0.437 |
Table 2 row theta_CL_GFR = 0.437 (RSE 23.8%); Eq. 6 |
| GFR centering constant | 71.88 mL/min/1.73 m^2 |
Eq. 6 prints CL = 1.03 * (GFR/71.88)^0.437 * e^0.29;
Table 1 gives the same population median rounded to 71.9 |
etalcl ~ 0.290 |
0.539^2 |
Table 2 IIV row CL = 53.9% (RSE 10.1%); Eq. 6 prints
e^0.29
|
etalvc ~ 0.368 |
0.607^2 |
Table 2 IIV row V1 = 60.7% (RSE 23.9%); Eq. 7 prints
e^0.37
|
etalq ~ 0.295 |
0.543^2 |
Table 2 IIV row Q = 54.3% (RSE 15.5%); Eq. 8 prints
e^0.29
|
etalvp ~ 0.103 |
0.321^2 |
Table 2 IIV row V2 = 32.1% (RSE 16.0%); Eq. 9 prints
e^0.10
|
propSd <- 0.174 |
0.174 (= 17.4%) |
Table 2 Residual error row Proportional error = 17.4% |
cl <- exp(lcl + etalcl) * (CRCL/71.88)^e_crcl_cl |
n/a | Eq. 6 |
d/dt(central) <- -kel*central - k12*central + k21*peripheral1 |
n/a | Results 3.2: “a two-compartment model with proportional residual best described the data … the ADVAN3, TRANS4 subroutines were selected” |
d/dt(peripheral1) <- k12*central - k21*peripheral1 |
n/a | Results 3.2: same |
Cc ~ prop(propSd) |
n/a | Eq. 5: C_ij = C_pred,ij * (1 + eps_prop,ij)
|
Squaring the Table 2 interindividual-variability percentages
reproduces the exponents printed in equations 6-9 exactly (0.539^2 =
0.290 vs the printed 0.29; 0.607^2 = 0.368 vs 0.37; 0.543^2 = 0.295 vs
0.29; 0.321^2 = 0.103 vs 0.10). That cross-check establishes that Chen
2023 reports interindividual variability as omega (the standard
deviation on the log scale) x 100, the usual NONMEM approximate-CV
convention, rather than as sqrt(exp(omega^2) - 1). The
packaged model therefore uses the squared Table 2 percentages, which are
one significant figure more precise than the two-decimal exponents
printed in the equations.
Virtual cohort
Chen 2023 section 2.6 specifies the Monte Carlo design: a typical 65 kg patient, five GFR strata (15, 30, 60, 90 and 120 mL/min/1.73 m^2), 1,000 simulations per candidate regimen, and a concentration-time profile simulated from 0 to 264 h. The thirteen regimens tabulated in Table 3 are reconstructed below from that table’s Day 1 / Day 2 / Day 3 / Day 4 columns, reading “Day 1” as 0-24 h, “Day 2” as 24-48 h, “Day 3” as 48-72 h and “Day 4” as 72 h onward. Under that reading every regimen’s loading phase matches the prose in section 3.4 and the Discussion (for example the GFR 90-120 recommendation of “15 mg/kg q12h for 5 times” resolves to doses at 0, 12, 24, 36 and 48 h).
The vignette uses 200 virtual subjects per regimen rather than the paper’s 1,000 to stay inside the pkgdown render budget. That is enough to resolve the median and the 2.5th-97.5th percentile band; the residual Monte Carlo noise is quantified below.
set.seed(20260728)
n_per_regimen <- 200L
wt_typical <- 65 # Chen 2023 section 2.6: "to a typical 65 kg patient"
t_end <- 264 # Chen 2023 section 2.6: "simulated between 0 and 264 h"
infusion_h <- 1 # Chen 2023 section 2.2: infusion duration 30-60 min
# Chen 2023 Table 3, one row per simulated regimen. `ld_times` are the loading
# doses (all at `ld_mgkg`); maintenance dosing starts at `md_start` and repeats
# every `md_int` hours at `md_mgkg`.
regimens <- tibble::tribble(
~regimen, ~CRCL, ~ld_mgkg, ~ld_times, ~md_mgkg, ~md_start, ~md_int,
"120-A", 120, 15, c(0, 12, 24), 15, 48, 24,
"120-B", 120, 15, c(0, 12, 24, 36, 48), 7.5, 72, 24,
"120-C", 120, 15, c(0, 12, 24, 36, 48), 15, 72, 24,
"90-A", 90, 15, c(0, 12, 24), 15, 48, 24,
"90-B", 90, 15, c(0, 12, 24, 36, 48), 7.5, 72, 24,
"90-C", 90, 15, c(0, 12, 24, 36, 48), 15, 72, 24,
"60-A", 60, 15, c(0, 12, 24, 48), 7.5, 72, 24,
"60-B", 60, 15, c(0, 12, 24, 48), 15, 72, 48,
"30-A", 30, 15, c(0, 12, 24, 48), 7.5, 72, 24,
"30-B", 30, 15, c(0, 12, 24, 48), 15, 72, 48,
"15-A", 15, 12, c(0, 12, 24, 48), 12, 72, 72,
"15-B", 15, 15, c(0, 12, 24, 48), 5, 72, 24,
"15-C", 15, 15, c(0, 12, 24, 48), 15, 72, 72
)
# Observation grid: every 4 h across the whole profile for the concentration-time
# figure, densified around the two published trough times (72 h and 240 h) and
# across the 216-240 h window used for the AUC0-24 calculation.
obs_times <- sort(unique(c(
seq(0, t_end, by = 4),
seq(48, 72, by = 2),
seq(216, 240, by = 1),
c(216.5, 217, 217.5, 240)
)))
make_regimen <- function(i) {
r <- regimens[i, ]
ids <- (i - 1L) * n_per_regimen + seq_len(n_per_regimen)
md_times <- seq(r$md_start, t_end, by = r$md_int)
d_times <- c(r$ld_times[[1]], md_times)
d_amts <- c(rep(r$ld_mgkg * wt_typical, length(r$ld_times[[1]])),
rep(r$md_mgkg * wt_typical, length(md_times)))
doses <- tidyr::expand_grid(id = ids, dose_idx = seq_along(d_times)) |>
dplyr::mutate(
time = d_times[dose_idx],
amt = d_amts[dose_idx],
rate = d_amts[dose_idx] / infusion_h, # rate = amt / duration -> 1 h infusion
evid = 1L,
cmt = "central"
) |>
dplyr::select(-dose_idx)
obs <- tidyr::expand_grid(id = ids, time = obs_times) |>
dplyr::mutate(
amt = NA_real_,
rate = NA_real_,
evid = 0L,
cmt = "central" # the model's only algebraic observable is Cc = central / vc;
# observation rows must name the ODE state, not the observable
)
dplyr::bind_rows(doses, obs) |>
dplyr::mutate(CRCL = r$CRCL, regimen = r$regimen) |>
dplyr::arrange(id, time, -evid)
}
events <- dplyr::bind_rows(lapply(seq_len(nrow(regimens)), make_regimen))
regimen_levels <- regimens$regimen
events <- events |> dplyr::mutate(regimen = factor(regimen, levels = regimen_levels))Simulation
mod <- readModelDb("Chen_2023_teicoplanin")
sim <- rxode2::rxSolve(
object = mod,
events = events,
keep = c("regimen", "CRCL")
) |>
as.data.frame() |>
dplyr::mutate(regimen = factor(regimen, levels = regimen_levels))
#> ℹ parameter labels from comments will be replaced by 'label()'Replicate published figures
Table 3 – trough concentrations at 72 h and 240 h
Chen 2023 Table 3 reports the median and 95% prediction interval of
Cmin,72h (day 4 trough, the loading-dose metric) and
Cmin,240h (day 11 trough at steady state, the
maintenance-dose metric) for each regimen. Both are concentrations read
at a fixed clock time rather than NCA-derived quantities, so they are
taken directly from the simulated profile.
published_troughs <- tibble::tribble(
~regimen, ~cmin72_pub, ~cmin240_pub,
"120-A", 12.18, 19.04,
"120-B", 15.45, 12.12,
"120-C", 15.11, 19.87,
"90-A", 13.09, 21.28,
"90-B", 16.73, 13.57,
"90-C", 16.91, 22.18,
"60-A", 15.15, 15.37,
"60-B", 14.74, 16.93,
"30-A", 17.94, 20.13,
"30-B", 17.97, 22.33,
"15-A", 16.28, 19.08,
"15-B", 20.27, 20.66,
"15-C", 20.26, 23.72
)
trough_sim <- sim |>
dplyr::filter(time %in% c(72, 240)) |>
dplyr::group_by(regimen, time) |>
dplyr::summarise(
med = stats::median(Cc),
lo = stats::quantile(Cc, 0.025),
hi = stats::quantile(Cc, 0.975),
.groups = "drop"
) |>
dplyr::mutate(txt = sprintf("%.2f [%.2f-%.2f]", med, lo, hi))
trough_tbl <- regimens |>
dplyr::select(regimen, CRCL) |>
dplyr::left_join(published_troughs, by = "regimen") |>
dplyr::left_join(
trough_sim |> dplyr::filter(time == 72) |>
dplyr::select(regimen, cmin72_sim = txt, cmin72_med = med),
by = "regimen"
) |>
dplyr::left_join(
trough_sim |> dplyr::filter(time == 240) |>
dplyr::select(regimen, cmin240_sim = txt, cmin240_med = med),
by = "regimen"
) |>
dplyr::mutate(
d72 = sprintf("%+.1f%%", 100 * (cmin72_med - cmin72_pub) / cmin72_pub),
d240 = sprintf("%+.1f%%", 100 * (cmin240_med - cmin240_pub) / cmin240_pub)
) |>
dplyr::select(regimen, CRCL, cmin72_pub, cmin72_sim, d72,
cmin240_pub, cmin240_sim, d240) |>
dplyr::rename(
"Regimen" = regimen,
"GFR (mL/min/1.73 m^2)" = CRCL,
"Cmin,72h published" = cmin72_pub,
"Cmin,72h simulated" = cmin72_sim,
"% diff (72 h)" = d72,
"Cmin,240h published" = cmin240_pub,
"Cmin,240h simulated" = cmin240_sim,
"% diff (240 h)" = d240
)
knitr::kable(
trough_tbl,
caption = paste0(
"Chen 2023 Table 3 replication. Published values are the median [95% ",
"prediction interval] reported in Table 3 (n = 1,000 per regimen); ",
"simulated values are the median [2.5th-97.5th percentile] from ",
n_per_regimen, " virtual subjects per regimen using the packaged model. ",
"All doses in mg/kg applied to a typical 65 kg patient."
)
)| Regimen | GFR (mL/min/1.73 m^2) | Cmin,72h published | Cmin,72h simulated | % diff (72 h) | Cmin,240h published | Cmin,240h simulated | % diff (240 h) |
|---|---|---|---|---|---|---|---|
| 120-A | 120 | 12.18 | 13.65 [3.76-24.89] | +12.0% | 19.04 | 20.52 [4.94-49.94] | +7.8% |
| 120-B | 120 | 15.45 | 16.26 [5.05-32.65] | +5.3% | 12.12 | 12.38 [2.47-30.96] | +2.1% |
| 120-C | 120 | 15.11 | 15.52 [4.40-32.67] | +2.7% | 19.87 | 19.48 [3.53-50.01] | -2.0% |
| 90-A | 90 | 13.09 | 12.94 [3.63-24.45] | -1.2% | 21.28 | 20.47 [4.64-47.65] | -3.8% |
| 90-B | 90 | 16.73 | 18.10 [5.48-36.87] | +8.2% | 13.57 | 14.68 [2.67-35.31] | +8.2% |
| 90-C | 90 | 16.91 | 18.49 [5.16-32.79] | +9.3% | 22.18 | 23.93 [6.29-53.22] | +7.9% |
| 60-A | 60 | 15.15 | 16.51 [5.55-29.75] | +9.0% | 15.37 | 16.77 [4.24-38.45] | +9.1% |
| 60-B | 60 | 14.74 | 14.78 [4.83-28.83] | +0.3% | 16.93 | 16.58 [4.06-36.22] | -2.1% |
| 30-A | 30 | 17.94 | 18.76 [7.78-32.26] | +4.6% | 20.13 | 22.02 [6.79-41.77] | +9.4% |
| 30-B | 30 | 17.97 | 18.40 [8.79-31.80] | +2.4% | 22.33 | 24.02 [9.55-45.01] | +7.6% |
| 15-A | 15 | 16.28 | 16.83 [8.48-31.53] | +3.4% | 19.08 | 19.96 [9.15-34.86] | +4.6% |
| 15-B | 15 | 20.27 | 19.95 [11.40-32.54] | -1.6% | 20.66 | 19.02 [7.50-36.63] | -8.0% |
| 15-C | 15 | 20.26 | 20.43 [10.42-36.64] | +0.8% | 23.72 | 24.21 [9.64-45.13] | +2.1% |
Every regimen reproduces to within 12% on Cmin,72h and
within 10% on Cmin,240h, with no systematic bias in either
direction. Part of the remaining spread is Monte Carlo noise rather than
model disagreement, and the table contains an internal ruler for it:
regimens 60-A/60-B and
30-A/30-B have identical dosing
through 72 h and differ only in their day-4 maintenance dose, so their
true Cmin,72h values must be equal. The published pairs
nevertheless differ by 0.41 mg/L (15.15 vs 14.74) and 0.03 mg/L (17.94
vs 17.97), and the simulated pairs by 1.73 mg/L (16.51 vs 14.78) and
0.36 mg/L (18.76 vs 18.40). The simulated spread is the larger of the
two, as expected from resampling 200 rather than 1,000 subjects per arm,
and it is of the same order as the largest published-vs-simulated
discrepancy in the table – so most of that discrepancy is attributable
to Monte Carlo noise rather than to a difference in the implemented
model.
Figure 3 – loading-dose effect on the day-4 trough
Chen 2023 Figure 3 plots the median Cmin,72h achieved by
different loading-dose regimens, stratified by GFR, with panels A and B
contrasting 3-dose and 5-dose loading. The paper’s headline conclusion
is that at least 12 mg/kg per dose is required to reach the
Cmin,72h >= 15 mg/L target regardless of renal function,
and that increasing the number of loading doses is more effective than
increasing the unit dose (Discussion: “take the Cmin,72h of 10 mg/kg for
5 administrations compared to 12 mg/kg for 3 administrations in Figure
3A as an example”).
set.seed(20260729)
ld_grid <- tidyr::expand_grid(
CRCL = c(15, 30, 60, 90, 120),
ld_mgkg = c(10, 12, 15),
n_load = c(3L, 5L)
) |>
dplyr::mutate(arm = paste0(ld_mgkg, " mg/kg x ", n_load, " (GFR ", CRCL, ")"))
make_ld_arm <- function(i) {
g <- ld_grid[i, ]
ids <- (i - 1L) * n_per_regimen + seq_len(n_per_regimen)
# 3-dose loading: q12h at 0, 12, 24 then the day-3 dose at 48 h.
# 5-dose loading: q12h at 0, 12, 24, 36, 48. Both end with a dose at 48 h,
# so Cmin,72h is the trough immediately before the day-4 dose in each case.
d_times <- if (g$n_load == 3L) c(0, 12, 24, 48) else c(0, 12, 24, 36, 48)
doses <- tidyr::expand_grid(id = ids, dose_idx = seq_along(d_times)) |>
dplyr::mutate(
time = d_times[dose_idx],
amt = g$ld_mgkg * wt_typical,
rate = g$ld_mgkg * wt_typical / infusion_h,
evid = 1L, cmt = "central"
) |>
dplyr::select(-dose_idx)
obs <- tibble::tibble(id = ids) |>
tidyr::expand_grid(time = c(0, 24, 48, 60, 72)) |>
dplyr::mutate(amt = NA_real_, rate = NA_real_, evid = 0L, cmt = "central")
dplyr::bind_rows(doses, obs) |>
dplyr::mutate(CRCL = g$CRCL, ld_mgkg = g$ld_mgkg, n_load = g$n_load) |>
dplyr::arrange(id, time, -evid)
}
ld_events <- dplyr::bind_rows(lapply(seq_len(nrow(ld_grid)), make_ld_arm))
ld_sim <- rxode2::rxSolve(
mod, events = ld_events, keep = c("CRCL", "ld_mgkg", "n_load")
) |>
as.data.frame()
ld_summary <- ld_sim |>
dplyr::filter(time == 72) |>
dplyr::group_by(CRCL, ld_mgkg, n_load) |>
dplyr::summarise(cmin72 = stats::median(Cc), .groups = "drop") |>
dplyr::mutate(
panel = factor(
ifelse(n_load == 3L, "A: 3 loading doses q12h", "B: 5 loading doses q12h"),
levels = c("A: 3 loading doses q12h", "B: 5 loading doses q12h")
),
dose_label = factor(paste0(ld_mgkg, " mg/kg"),
levels = paste0(c(10, 12, 15), " mg/kg"))
)
ggplot(ld_summary, aes(x = factor(CRCL), y = cmin72, fill = dose_label)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_hline(yintercept = 15, linetype = "dashed") +
facet_wrap(~panel) +
labs(
x = "GFR (mL/min/1.73 m^2)",
y = "Median Cmin,72h (mg/L)",
fill = "Loading unit dose",
title = "Replicates Figure 3 of Chen 2023",
subtitle = paste0("Median day-4 trough by loading-dose regimen and renal ",
"function; dashed line = 15 mg/L target")
) +
theme_minimal()
ld_check <- ld_summary |>
dplyr::select(CRCL, dose_label, n_load, cmin72) |>
tidyr::pivot_wider(names_from = n_load, values_from = cmin72,
names_prefix = "n") |>
dplyr::rename(
"GFR (mL/min/1.73 m^2)" = CRCL,
"Loading unit dose" = dose_label,
"Median Cmin,72h, 3 doses" = n3,
"Median Cmin,72h, 5 doses" = n5
)
knitr::kable(
ld_check,
digits = 2,
caption = paste0("Median Cmin,72h (mg/L) underlying the Figure 3 ",
"replication; target is 15 mg/L.")
)| GFR (mL/min/1.73 m^2) | Loading unit dose | Median Cmin,72h, 3 doses | Median Cmin,72h, 5 doses |
|---|---|---|---|
| 15 | 10 mg/kg | 14.05 | 17.98 |
| 15 | 12 mg/kg | 16.84 | 21.94 |
| 15 | 15 mg/kg | 20.39 | 25.53 |
| 30 | 10 mg/kg | 13.02 | 15.87 |
| 30 | 12 mg/kg | 14.23 | 18.71 |
| 30 | 15 mg/kg | 18.11 | 23.65 |
| 60 | 10 mg/kg | 9.87 | 13.25 |
| 60 | 12 mg/kg | 11.93 | 15.67 |
| 60 | 15 mg/kg | 15.01 | 20.33 |
| 90 | 10 mg/kg | 9.01 | 11.03 |
| 90 | 12 mg/kg | 11.38 | 13.15 |
| 90 | 15 mg/kg | 12.98 | 17.16 |
| 120 | 10 mg/kg | 8.05 | 10.78 |
| 120 | 12 mg/kg | 9.99 | 12.77 |
| 120 | 15 mg/kg | 13.21 | 16.55 |
The replication recovers the paper’s stratified loading-dose recommendations exactly. Chen 2023 section 3.4 concludes that “for patients with GFR 90-120 mL/min/1.73 m^2, a loading dose of 15 mg/kg for 5 times made it possible to achieve a Cmin,72h of >= 15 mg/L; for patients with GFR 30-60 mL/min/1.73 m^2, a loading dosage regimen of 15 mg/kg for 3 times was enough, while for patients with GFR 15 mL/min/1.73 m^2, the loading dosage may be reduced to 12 mg/kg for 3 times”. Reading the table above against the 15 mg/L target gives precisely that partition: 15 mg/kg x 3 falls short at GFR 120 and 90 (13.21 and 12.98 mg/L) but clears the target at GFR 60 and 30 (15.01 and 18.11); 15 mg/kg x 5 clears it at GFR 120 and 90 (16.55 and 17.16); and 12 mg/kg x 3 clears it at GFR 15 (16.84) while falling short at every higher GFR. The 10 mg/kg arm misses the target at every GFR level with either 3 or 5 loading doses, supporting the paper’s headline claim that “at least 800 mg (about 12 mg/kg) is required”.
The paper’s secondary claim – that adding loading doses beats raising the unit dose – also holds, though less cleanly. The 10 mg/kg x 5 arm exceeds the 12 mg/kg x 3 arm at four of the five GFR strata (GFR 15, 30, 60 and 120); at GFR 90 the two are effectively tied (11.03 vs 11.38 mg/L), a gap well inside the Monte Carlo noise established in the Table 3 replication above. Median troughs otherwise rise as GFR falls at every unit dose, with a single inversion between the GFR 120 and GFR 90 strata of the 15 mg/kg x 3 arm (13.21 vs 12.98 mg/L) that is likewise within resampling noise.
Figure 4 – probability of target attainment against MRSA
Chen 2023 Figure 4 plots the PTA for
AUC0-24/MIC >= 610 across MIC values of 0.25, 0.5, 1, 2
and 4 mg/L. The key published findings are that the vast majority of
regimens attain the target at MIC 0.5 mg/L, that PTA falls to
“33.1%-74.4%” at MIC 1 mg/L, and that no simulated
regimen reaches the 90% PTA target at MIC 1 mg/L.
The PTA calculation needs each subject’s 24-h AUC, which is computed with PKNCA in the next section; the figure is therefore rendered after the NCA block.
PKNCA on the simulated cohort
AUC0-24 is computed over the 216-240 h window. That
window is inferred rather than stated: Chen 2023 says only that “AUC0-24
values estimated by the linear trapezoidal method from the
concentration-time profiles were divided by putative MIC values”,
without naming the interval. The 216-240 h window is the 24 h
immediately preceding the published Cmin,240h timepoint,
and every one of the thirteen regimens has a dose at exactly t = 216 h
(q24h, q48h from 72 h and q72h from 72 h all land on 216), so it is a
complete post-dose dosing interval for all of them. It is also the only
candidate window that reproduces the published values for the q48h and
q72h regimens; see Assumptions and deviations below.
conc_nca <- sim |>
dplyr::filter(!is.na(Cc)) |>
dplyr::select(id, time, Cc, regimen)
dose_nca <- events |>
dplyr::filter(evid == 1L) |>
dplyr::select(id, time, amt, regimen)
conc_obj <- PKNCA::PKNCAconc(
conc_nca, Cc ~ time | regimen + id,
concu = "mg/L", timeu = "hr"
)
dose_obj <- PKNCA::PKNCAdose(
dose_nca, amt ~ time | regimen + id,
doseu = "mg"
)
intervals <- data.frame(
start = 216,
end = 240,
cmax = TRUE,
tmax = TRUE,
cmin = TRUE,
cav = TRUE,
auclast = TRUE
)
nca_res <- PKNCA::pk.nca(
PKNCA::PKNCAdata(conc_obj, dose_obj, intervals = intervals)
)
knitr::kable(
summary(nca_res),
caption = paste0(
"Steady-state NCA over the 216-240 h dosing interval for each of the ",
"thirteen Chen 2023 Table 3 regimens (geometric mean [geometric CV%]; ",
"Tmax median [range])."
)
)| Interval Start | Interval End | regimen | N | AUClast (hr*mg/L) | Cmax (mg/L) | Cmin (mg/L) | Tmax (hr) | Cav (mg/L) |
|---|---|---|---|---|---|---|---|---|
| 216 | 240 | 120-A | 200 | 686 [44.0] | 63.2 [41.2] | 18.3 [65.7] | 1.00 [1.00, 1.00] | 28.6 [44.0] |
| 216 | 240 | 120-B | 200 | 390 [49.7] | 36.5 [39.8] | 10.9 [74.9] | 1.00 [1.00, 1.00] | 16.2 [49.7] |
| 216 | 240 | 120-C | 200 | 674 [47.5] | 65.5 [46.2] | 18.0 [70.5] | 1.00 [1.00, 1.00] | 28.1 [47.5] |
| 216 | 240 | 90-A | 200 | 691 [44.2] | 65.5 [39.0] | 18.5 [64.9] | 1.00 [1.00, 1.00] | 28.8 [44.2] |
| 216 | 240 | 90-B | 200 | 436 [51.9] | 37.2 [39.5] | 12.8 [73.1] | 1.00 [1.00, 1.00] | 18.2 [51.9] |
| 216 | 240 | 90-C | 200 | 791 [41.6] | 67.9 [38.3] | 22.4 [61.1] | 1.00 [1.00, 1.00] | 33.0 [41.6] |
| 216 | 240 | 60-A | 200 | 497 [43.2] | 39.2 [35.0] | 15.3 [60.3] | 1.00 [1.00, 1.00] | 20.7 [43.2] |
| 216 | 240 | 60-B | 200 | 605 [36.7] | 59.9 [42.8] | 12.9 [63.1] | 1.00 [1.00, 1.00] | 25.2 [36.7] |
| 216 | 240 | 30-A | 200 | 615 [35.7] | 43.1 [33.1] | 20.0 [47.4] | 1.00 [1.00, 1.00] | 25.6 [35.7] |
| 216 | 240 | 30-B | 200 | 747 [31.3] | 59.8 [40.0] | 18.2 [49.3] | 1.00 [1.00, 1.00] | 31.1 [31.3] |
| 216 | 240 | 15-A | 200 | 629 [28.0] | 49.0 [38.7] | 15.4 [41.0] | 1.00 [1.00, 1.00] | 26.2 [28.0] |
| 216 | 240 | 15-B | 200 | 542 [36.8] | 34.6 [34.6] | 18.6 [44.7] | 1.00 [1.00, 1.00] | 22.6 [36.8] |
| 216 | 240 | 15-C | 200 | 768 [31.7] | 65.8 [38.2] | 18.4 [49.7] | 1.00 [1.00, 1.00] | 32.0 [31.7] |
Why 216-240 h and not another 24-h window
The three candidate windows are compared against the published
AUC0-24 below, so the choice above is evidence-based rather
than asserted. Note that the 0-24 h and 240-264 h windows are evaluated
on this vignette’s coarser 4-hourly grid outside 216-240 h, which adds
some trapezoidal error; the discrepancies they show are far larger than
that error.
# Chen 2023 Table 3, AUC0-24/MIC column at MIC = 1 mg/L, which is numerically
# equal to AUC0-24 in mg*h/L.
published_auc <- tibble::tribble(
~regimen, ~auclast,
"120-A", 687,
"120-B", 413.9,
"120-C", 703,
"90-A", 734.7,
"90-B", 446.9,
"90-C", 775.7,
"60-A", 497.7,
"60-B", 625.2,
"30-A", 618.2,
"30-B", 761.2,
"15-A", 647.7,
"15-B", 587.6,
"15-C", 802.3
)
window_intervals <- data.frame(
start = c(0, 216, 240),
end = c(24, 240, 264),
auclast = TRUE
)
window_res <- PKNCA::pk.nca(
PKNCA::PKNCAdata(conc_obj, dose_obj, intervals = window_intervals)
)
window_tbl <- as.data.frame(window_res$result) |>
dplyr::filter(PPTESTCD == "auclast") |>
dplyr::group_by(regimen, start) |>
dplyr::summarise(auc = stats::median(PPORRES), .groups = "drop") |>
dplyr::mutate(window = paste0(start, "-", start + 24, " h")) |>
dplyr::select(regimen, window, auc) |>
tidyr::pivot_wider(names_from = window, values_from = auc) |>
dplyr::left_join(published_auc, by = "regimen") |>
dplyr::mutate(
md_int = regimens$md_int[match(regimen, regimens$regimen)]
) |>
dplyr::select(regimen, md_int, auclast, `0-24 h`, `216-240 h`, `240-264 h`) |>
dplyr::rename(
"Regimen" = regimen,
"Maintenance interval (h)" = md_int,
"Published AUC0-24" = auclast,
"Simulated, 0-24 h" = `0-24 h`,
"Simulated, 216-240 h" = `216-240 h`,
"Simulated, 240-264 h" = `240-264 h`
)
knitr::kable(
window_tbl,
digits = 0,
caption = paste0(
"Median simulated AUC (mg*h/L) over three candidate 24-h windows versus ",
"the published AUC0-24. Only the 216-240 h window tracks the published ",
"values across all maintenance intervals."
)
)| Regimen | Maintenance interval (h) | Published AUC0-24 | Simulated, 0-24 h | Simulated, 216-240 h | Simulated, 240-264 h |
|---|---|---|---|---|---|
| 120-A | 24 | 687 | 335 | 734 | 674 |
| 120-B | 24 | 414 | 324 | 405 | 364 |
| 120-C | 24 | 703 | 312 | 691 | 614 |
| 90-A | 24 | 735 | 330 | 705 | 644 |
| 90-B | 24 | 447 | 339 | 453 | 416 |
| 90-C | 24 | 776 | 347 | 787 | 717 |
| 60-A | 24 | 498 | 348 | 538 | 497 |
| 60-B | 48 | 625 | 363 | 597 | 356 |
| 30-A | 24 | 618 | 381 | 643 | 609 |
| 30-B | 48 | 761 | 383 | 761 | 529 |
| 15-A | 72 | 648 | 332 | 632 | 446 |
| 15-B | 24 | 588 | 414 | 543 | 527 |
| 15-C | 72 | 802 | 407 | 796 | 546 |
The 0-24 h window is uniformly too low and does not order the
regimens as published, because it covers the loading phase before
accumulation. The 240-264 h window agrees for the q24h regimens but
collapses for the q48h and q72h ones (60-B,
30-B, 15-A, 15-C), since for
those it is the second half of a dosing interval rather than a complete
one. Only 216-240 h – a complete post-dose interval for all thirteen
regimens – reproduces the published values throughout.
Comparison against published NCA
Chen 2023 Table 3 reports AUC0-24/MIC at MIC = 1 mg/L,
which is numerically equal to AUC0-24 in mg*h/L. The table
below compares the published values against the simulated
AUClast over the 216-240 h interval.
sim_nca <- as.data.frame(nca_res$result) |>
dplyr::filter(PPTESTCD == "auclast") |>
dplyr::select(regimen, PPTESTCD, PPORRES)
auc_cmp <- nlmixr2lib::ncaComparisonTable(
simulated = sim_nca,
reference = published_auc,
by = "regimen",
units = c(auclast = "mg*h/L")
)
knitr::kable(
auc_cmp,
caption = paste0(
"Simulated versus published AUC0-24 (equivalently AUC0-24/MIC at ",
"MIC = 1 mg/L, Chen 2023 Table 3). Simulated values are the median ",
"across ", n_per_regimen, " virtual subjects per regimen."
)
)| NCA parameter | regimen | Reference | Simulated | % diff |
|---|---|---|---|---|
| AUClast (mg*h/L) | 120-A | 687 | 734 | +6.9% |
| AUClast (mg*h/L) | 120-B | 414 | 405 | -2.1% |
| AUClast (mg*h/L) | 120-C | 703 | 691 | -1.7% |
| AUClast (mg*h/L) | 90-A | 735 | 705 | -4.1% |
| AUClast (mg*h/L) | 90-B | 447 | 453 | +1.4% |
| AUClast (mg*h/L) | 90-C | 776 | 787 | +1.5% |
| AUClast (mg*h/L) | 60-A | 498 | 538 | +8.2% |
| AUClast (mg*h/L) | 60-B | 625 | 597 | -4.4% |
| AUClast (mg*h/L) | 30-A | 618 | 643 | +4.1% |
| AUClast (mg*h/L) | 30-B | 761 | 761 | -0.1% |
| AUClast (mg*h/L) | 15-A | 648 | 632 | -2.5% |
| AUClast (mg*h/L) | 15-B | 588 | 543 | -7.6% |
| AUClast (mg*h/L) | 15-C | 802 | 796 | -0.8% |
Every regimen agrees to within 10% of the published
AUC0-24, with no row exceeding the 20% flagging tolerance.
The residual differences are consistent with the combination of Monte
Carlo noise at 200 versus 1,000 subjects and the discretization of the
trapezoidal AUC onto this vignette’s observation grid.
Figure 4 (continued) – PTA at the AUC0-24/MIC target of 610
mic_values <- c(0.25, 0.5, 1, 2, 4)
pta <- as.data.frame(nca_res$result) |>
dplyr::filter(PPTESTCD == "auclast") |>
dplyr::select(regimen, id, auc = PPORRES) |>
tidyr::expand_grid(MIC = mic_values) |>
dplyr::group_by(regimen, MIC) |>
dplyr::summarise(pta = 100 * mean(auc / MIC >= 610), .groups = "drop") |>
dplyr::left_join(regimens |> dplyr::select(regimen, CRCL), by = "regimen")
ggplot(pta, aes(x = factor(MIC), y = pta, group = regimen, colour = regimen)) +
geom_line() +
geom_point(size = 1.5) +
geom_hline(yintercept = 90, linetype = "dashed") +
facet_wrap(~paste0("GFR ", CRCL), nrow = 1) +
labs(
x = "MIC (mg/L)",
y = "PTA for AUC0-24/MIC >= 610 (%)",
colour = "Regimen",
title = "Replicates Figure 4 of Chen 2023",
subtitle = "Dashed line = 90% PTA target"
) +
theme_minimal() +
theme(legend.position = "bottom")
pta_mic1 <- pta |>
dplyr::filter(MIC == 1) |>
dplyr::arrange(dplyr::desc(CRCL), regimen)
knitr::kable(
pta_mic1 |>
dplyr::select(regimen, CRCL, pta) |>
dplyr::rename(
"Regimen" = regimen,
"GFR (mL/min/1.73 m^2)" = CRCL,
"PTA at MIC = 1 mg/L (%)" = pta
),
digits = 1,
caption = "Simulated PTA for AUC0-24/MIC >= 610 at MIC = 1 mg/L."
)| Regimen | GFR (mL/min/1.73 m^2) | PTA at MIC = 1 mg/L (%) |
|---|---|---|
| 120-A | 120 | 64.0 |
| 120-B | 120 | 17.0 |
| 120-C | 120 | 62.0 |
| 90-A | 90 | 66.5 |
| 90-B | 90 | 24.5 |
| 90-C | 90 | 77.5 |
| 60-A | 60 | 33.5 |
| 60-B | 60 | 48.0 |
| 30-A | 30 | 54.0 |
| 30-B | 30 | 73.5 |
| 15-A | 15 | 56.0 |
| 15-B | 15 | 39.0 |
| 15-C | 15 | 77.5 |
# The six regimens Chen 2023 recommends (Discussion, final paragraph).
recommended <- c("120-C", "90-C", "60-B", "30-B", "15-A", "15-C")
pta_stats <- list(
mic1_max = max(pta_mic1$pta),
mic1_lo = min(pta_mic1$pta),
mic1_rec_lo = min(pta_mic1$pta[pta_mic1$regimen %in% recommended]),
mic1_rec_hi = max(pta_mic1$pta[pta_mic1$regimen %in% recommended]),
mic05_n90 = sum(pta$pta[pta$MIC == 0.5] >= 90),
mic05_min = min(pta$pta[pta$MIC == 0.5]),
mic05_short = paste(
sort(as.character(pta$regimen[pta$MIC == 0.5 & pta$pta < 90])),
collapse = ", "
),
mic1_below_pub = paste(
sort(as.character(pta_mic1$regimen[pta_mic1$pta < 33.1])),
collapse = ", "
),
mic2_max = max(pta$pta[pta$MIC == 2]),
n_regimens = nrow(pta_mic1)
)
str(pta_stats)
#> List of 10
#> $ mic1_max : num 77.5
#> $ mic1_lo : num 17
#> $ mic1_rec_lo : num 48
#> $ mic1_rec_hi : num 77.5
#> $ mic05_n90 : int 10
#> $ mic05_min : num 70.5
#> $ mic05_short : chr "120-B, 60-A, 90-B"
#> $ mic1_below_pub: chr "120-B, 90-B"
#> $ mic2_max : num 15.5
#> $ n_regimens : int 13The replication reproduces the paper’s decisive negative finding: the highest simulated PTA at MIC = 1 mg/L is 77.5%, so no regimen reaches the 90% target – matching “no dosage achieved 90% of PTA when MIC = 1 mg/L”.
The published PTA span at MIC = 1 mg/L is quoted as “33.1%-74.4% in patients with varying renal function”. The simulated span is 17.0%-77.5% across all 13 regimens and 48.0%-77.5% across the six the paper recommends. These brackets overlap the published range but do not coincide with it at either endpoint, because Chen 2023 does not state which subset of the Figure 4 regimens its quoted range summarises. The reduced-maintenance arms (120-B, 90-B) fall below the published 33.1% floor, while the best-performing arms sit slightly above 74.4%. The qualitative conclusion the paper draws from the figure – that MIC = 1 mg/L is out of reach at every clinically plausible dose – is reproduced unambiguously.
At MIC = 0.5 mg/L, 10 of 13 regimens clear the 90% target (lowest 70.5%), consistent with the paper’s “the vast majority of the listed regimens achieved PTA targets when MIC = 0.5 mg/L”. The arms that fall short are 120-B, 60-A, 90-B. At MIC = 2 mg/L the best regimen attains only 15.5%, so the target is unattainable across the board, as published.
Figure 2 – simulated concentration-time profile
Chen 2023 Figure 2 is a prediction-corrected VPC of the observed study data under the standard 400 mg regimen. The original concentrations are not publicly available, so a true pcVPC cannot be reproduced. The panel below instead shows the simulated median and 95% prediction band for the three regimens the paper recommends, illustrating the accumulation behaviour that drives the day-4 versus day-11 trough distinction.
vpc_band <- sim |>
dplyr::filter(regimen %in% c("120-C", "30-B", "15-A")) |>
dplyr::group_by(regimen, CRCL, time) |>
dplyr::summarise(
p025 = stats::quantile(Cc, 0.025),
p50 = stats::median(Cc),
p975 = stats::quantile(Cc, 0.975),
.groups = "drop"
) |>
dplyr::mutate(panel = paste0("GFR ", CRCL, " (regimen ", regimen, ")"))
ggplot(vpc_band, aes(x = time, y = p50)) +
geom_ribbon(aes(ymin = p025, ymax = p975), fill = "steelblue", alpha = 0.25) +
geom_line(colour = "steelblue4", linewidth = 0.7) +
geom_hline(yintercept = 15, linetype = "dashed") +
geom_vline(xintercept = c(72, 240), linetype = "dotted") +
facet_wrap(~panel, nrow = 1) +
labs(
x = "Time after first dose (hours)",
y = "Teicoplanin concentration (mg/L)",
title = "Simulated concentration-time profiles for the recommended regimens",
subtitle = paste0("Median and 2.5th-97.5th percentile band, n = ",
n_per_regimen, " per regimen; dashed line = 15 mg/L ",
"trough target, dotted lines = 72 h and 240 h")
) +
theme_minimal()
The profiles show why Chen 2023 recommends follow-up TDM at steady
state rather than relying on the day-4 trough alone: with a terminal
half-life near 100 h at the population-median GFR, concentrations are
still accumulating well past 72 h, so Cmin,72h
systematically understates the eventual steady-state exposure.
Assumptions and deviations
AUC0-24window inferred as 216-240 h. Chen 2023 section 2.6 states that the concentration-time profile was simulated between 0 and 264 h and thatAUC0-24values were obtained by the linear trapezoidal method, but never names the 24-h window. Three candidate windows were therefore tested against the thirteen published Table 3 values; the comparison is rendered live in the “Why 216-240 h and not another 24-h window” section above rather than asserted here. In summary: the first dosing interval (0-24 h) is uniformly too low and does not order the regimens as published, because it precedes accumulation; the 240-264 h window agrees for the q24h regimens but collapses for the q48h and q72h regimens, for which it is the second half of a dosing interval rather than a complete one; and the 216-240 h window reproduces all thirteen regimens to within 10%. It is also the only candidate that is a complete post-dose interval for every regimen, since q24h, q48h-from-72h and q72h-from-72h all place a dose at exactly t = 216 h. It is used throughout this vignette on that evidence. Should the authors have used a different window, the AUC-derived quantities here (AUC0-24 and the PTA / CFR analyses built on it) would shift, while the trough replications, which involve no window choice, would not.Table 3 dosing regimens reconstructed from the Day 1 / Day 2 / Day 3 / Day 4 column layout. Chen 2023 Table 3 specifies each regimen as four per-day cells (e.g. “15 mg/kg q12h” on Day 1, “15 mg/kg q24h” on Day 2). The vignette resolves these to explicit dose times by reading Day 1 as 0-24 h, Day 2 as 24-48 h, Day 3 as 48-72 h, and Day 4 as 72 h onward. This reading is corroborated by the paper’s prose: the GFR 90-120 recommendation of “5 loading doses of 15 mg/kg q12h” resolves to doses at 0, 12, 24, 36 and 48 h under it, and the GFR 30-60 recommendation of “3 loading doses of 15 mg/kg q12h followed by 15 mg/kg on Day 3 and 15 mg/kg q48h from Day 4” resolves to 0, 12, 24, then 48, then 72/120/168/216. The close agreement of the reproduced
Cmin,72hvalues confirms the reading.Infusion duration fixed at 1 h. Chen 2023 section 2.2 reports an infusion duration of 30-60 min for the clinical doses but does not state what was used in the Monte Carlo simulations. The vignette uses 1 h (the upper end of the reported range). Trough concentrations at 72 h and 240 h and the 24-h AUC are insensitive to this choice; only
CmaxandTmaxin the NCA table depend on it, and neither is reported in the paper.Doses computed as mg/kg x 65 kg rather than the paper’s rounded clinical equivalents. Chen 2023 section 2.6 specifies simulation “to a typical 65 kg patient” with mg/kg doses, so the vignette uses 975 mg for 15 mg/kg, 780 mg for 12 mg/kg, 487.5 mg for 7.5 mg/kg and 325 mg for 5 mg/kg. The Table 3 footnotes note that “15 mg/kg equates to approximately 1,000 mg” and “12 mg/kg equates to approximately 800 mg for the convenience of clinical operation”; those are clinical rounding recommendations for practice, not the simulated amounts.
Interindividual variability entered as omega^2 = (published %/100)^2. Chen 2023 Table 2 reports IIV as a bare percentage with no stated convention. Squaring those percentages reproduces the exponents printed in equations 6-9 exactly (see the Source trace section), which identifies the percentages as omega x 100 rather than
sqrt(exp(omega^2) - 1) x 100. Had the alternative convention been assumed, omega^2 for CL would have been 0.253 instead of 0.290 and the reproduced prediction intervals would have been visibly too narrow.Independent (diagonal) IIV on CL, V1, Q and V2. Chen 2023 Table 2 reports four diagonal IIV terms and no off-diagonal covariances, and no supplement containing the NONMEM control stream is on disk. The packaged model therefore uses independent etas. If the original model estimated an OMEGA block, the reproduced prediction intervals would be somewhat mis-shaped even though the medians match; the close agreement of the published 95% prediction intervals with the simulated ones in the Table 3 replication suggests any correlation was modest.
Cumulative fraction of response (Figure 5) not reproduced. Chen 2023 computes CFR by weighting the PTA at each MIC by the EUCAST MRSA MIC distribution. The paper states only that “most MRSA had an MIC distribution for teicoplanin of 0.5-1 mg/L” and does not tabulate the per-MIC isolate fractions
p(MIC_i)used in its Equation 4, and the EUCAST distribution is not on disk. Reproducing Figure 5 would require inventing those weights, so it is omitted. The PTA values that feed the CFR calculation are reproduced above.Race / ethnicity not modeled. Chen 2023 does not report race composition by category; the Conclusion describes the cohort as “a prospective cohort of Chinese septic patients”. Race was not among the screened covariates.
Screened-but-not-retained covariates documented in metadata, not
covariateData. Chen 2023 screened sex, age, height, weight, BMI, ALT, AST, total and direct bilirubin, total protein, albumin, white blood count, serum creatinine and blood urea nitrogen; only GFR on CL was retained. Per the standing nlmixr2lib pattern these are recorded inpopulation$screened_covariatesrather than added tocovariateData, which would trigger a “declared but not referenced” convention warning.CRCLcanonical column used for a CKD-EPI eGFR. The canonicalCRCLcolumn ininst/references/covariate-columns.mdcovers BSA-normalized renal function from either a creatinine-based estimate (MDRD or CKD-EPI eGFR) or a tracer-measured GFR. Chen 2023 uses the CKD-EPI equation (Levey 2009), which the register explicitly lists; the assay form is documented incovariateData[[CRCL]]$descriptionas required. No new canonical was introduced.Model not defined for renal replacement therapy. Patients receiving RRT were excluded from the study by protocol, so the GFR power term is uncalibrated in dialysis patients. Note that the sibling packaged model
Wi_2017_teicoplanindoes carry a CRRT covariate and may be more appropriate for that population.Virtual cohort uses n = 200 per regimen (vs n = 1,000 in the paper). The vignette has a 5-minute pkgdown render budget and simulates 13 Table 3 regimens plus 30 loading-dose arms for the Figure 3 replication. n = 200 per arm resolves the median and 95% prediction band adequately; the residual Monte Carlo noise is quantified in the Table 3 replication narrative using the
60-A/60-Band30-A/30-Bpairs, which share identical dosing through 72 h.