Teicoplanin (Zhao 2015)
Source:vignettes/articles/Zhao_2015_teicoplanin.Rmd
Zhao_2015_teicoplanin.RmdModel and source
- Citation: Zhao W, Zhang D, Storme T, Baruchel A, Decleves X, Jacqz-Aigrain E. Population pharmacokinetics and dosing optimization of teicoplanin in children with malignant haematological disease. Br J Clin Pharmacol. 2015;80(5):1197-1207. doi:10.1111/bcp.12710
- Description: Two-compartment IV-injection population PK model for teicoplanin in 85 children with malignant hematological disease (Zhao 2015). Body weight enters Vc and Vp with the fixed allometric exponent 1 and enters CL and Q with the fixed allometric exponent 0.75; Schwartz-formula creatinine clearance enters CL via a power exponent estimated at 0.606. Reference subject: WT = 27.1 kg, CRCL = 179 mL/min. The published model was used to derive age-band mg/kg dosing (18 mg/kg for infants, 14 mg/kg for children, 12 mg/kg for adolescents) and a patient-tailored daily dose (target AUC * CL_i) to attain the AUC(0,24 h) target of 750 mg.L/h.
- Article: Br J Clin Pharmacol 2015;80(5):1197-1207
Population
The model was developed from 143 teicoplanin serum concentrations (123 TDM samples + 20 opportunistic samples) in 85 children (53 male, 32 female) with malignant hematological disease admitted to the Department of Paediatric Haemato-Oncology at Robert Debre Hospital (Paris) between 2012 and 2013. Median age was 8.1 years (range 0.5-16.9; mean 8.4, SD 4.6); median body weight 27.1 kg (range 7.7-90.6; mean 32.3, SD 17.8); median serum creatinine 33 umol/L (range 12-121); median Schwartz-formula creatinine clearance 178.9 mL/min/1.73 m^2 (range 48.6-464.1). 34 of 85 patients had received a bone marrow transplant. The underlying haematological diagnoses were acute lymphoblastic leukaemia (41), acute myeloblastic leukaemia (27), biphenotypic acute leukaemia (4), juvenile myelomonocytic leukaemia (3), lymphoma (5), and other (5). The cohort was stratified into three age groups: infants 1 month to 2 years (n=10), children 2-12 years (n=49), and adolescents 12-18 years (n=26). Patients received the standard regimen of 10 mg/kg every 12 h for three loading doses followed by 10 mg/kg once daily maintenance as a 3-5 min IV injection, with therapeutic drug monitoring targeting a steady-state trough concentration of >= 10 mg/L (Zhao 2015 Table 1).
The same information is available programmatically via
readModelDb("Zhao_2015_teicoplanin")$population.
Source trace
Every numeric value in ini() carries an in-file comment
pointing to the Zhao 2015 source location. The table below collects them
in one place for review.
| Equation / parameter | Value | Source location |
|---|---|---|
lvc (V1) |
12.9 L | Table 2, row “theta1” |
lvp (V2) |
25.2 L | Table 2, row “theta2” |
lq (Q) |
0.341 L/h | Table 2, row “theta3” |
lcl (CL) |
0.491 L/h | Table 2, row “theta4” |
e_wt_vc (fixed 1) |
1 | Results “allometric coefficients of 0.75 for CL and Q, 1 for V1 and V2” |
e_wt_vp (fixed 1) |
1 | Results (same sentence) |
e_wt_q (fixed 0.75) |
0.75 | Results (same sentence) |
e_wt_cl (fixed 0.75) |
0.75 | Results (same sentence) |
e_crcl_cl |
0.606 | Table 2, row “theta5” (RF factor) |
etalvc (22.2% CV) |
0.04811 | Table 2, IIV row “V1” |
etalq (131.5% CV) |
1.00402 | Table 2, IIV row “Q” |
etalcl (31.8% CV) |
0.09633 | Table 2, IIV row “CL” |
propSd |
0.148 (14.8%) | Table 2, row “Proportional” |
addSd |
1.1 mg/L | Table 2, row “Additive” |
| WT reference (27.1) | 27.1 kg | Results “the reference weight and creatinine clearance were the median values of our population, 27.1 kg and 179 ml min-1” |
| CRCL reference (179) | 179 mL/min/1.73 m^2 | Results (same sentence) |
| 2-cmt structural | n/a | Results “A two compartment model with first order elimination fitted the data” |
| add + prop residual | n/a | Results “Residual variability was best described by a combined proportional and additive model” |
| Target AUC(0,24h) | 750 mg.L/h | Methods / Discussion - PK-PD breakpoint for MRSA eradication |
Virtual cohort
Original observed data are not publicly available. The cohort below covers three age- / weight-bracket scenarios corresponding to the three paediatric strata defined in Zhao 2015 (infant, child, adolescent), each at a representative Schwartz-formula creatinine clearance. Each cohort receives the paper’s standard initial regimen (10 mg/kg Q12H for three loading doses, then 10 mg/kg QD) as a short IV injection. The per-dose mg amount is the integer milligram value closest to 10 mg/kg.
set.seed(20260619)
n_sub <- 80L
make_arm <- function(label, weight_kg, crcl, mg_per_dose, id_offset) {
ids <- id_offset + seq_len(n_sub)
# 3 loading doses Q12H (0, 12, 24 h) then QD maintenance through 168 h
load_times <- c(0, 12, 24)
maint_times <- seq(48, 168, by = 24)
dose_times <- c(load_times, maint_times)
infusion_dur_h <- 5 / 60 # 5-minute IV injection
dose_rows <- tidyr::expand_grid(id = ids, time = dose_times) |>
dplyr::mutate(
evid = 1L,
amt = mg_per_dose,
cmt = "central",
rate = mg_per_dose / infusion_dur_h,
cohort = label,
WT = weight_kg,
CRCL = crcl
)
obs_times <- sort(unique(c(
seq(0, 24, by = 0.5),
seq(24.5, 48, by = 0.5),
seq(49, 168, by = 1),
seq(168.5, 192, by = 0.5)
)))
obs_rows <- tidyr::expand_grid(id = ids, time = obs_times) |>
dplyr::mutate(
evid = 0L,
amt = 0,
cmt = NA_character_,
rate = 0,
cohort = label,
WT = weight_kg,
CRCL = crcl
)
dplyr::bind_rows(dose_rows, obs_rows) |> dplyr::arrange(id, time, dplyr::desc(evid))
}
events <- dplyr::bind_rows(
make_arm("infant_10kg_crcl180", 10, 180, 100, 0L),
make_arm("child_25kg_crcl180", 25, 180, 250, 100L),
make_arm("adol_55kg_crcl180", 55, 180, 550, 200L)
)
stopifnot(!anyDuplicated(unique(events[, c("id", "time", "evid")])))Simulation
mod <- readModelDb("Zhao_2015_teicoplanin")
sim <- rxode2::rxSolve(
mod,
events = events,
keep = c("cohort", "WT", "CRCL")
) |> as.data.frame()
#> ℹ parameter labels from comments will be replaced by 'label()'For typical-value (no-IIV) comparisons against the Zhao 2015 clearance relationship, also simulate with the random effects zeroed.
mod_typical <- mod |> rxode2::zeroRe()
#> ℹ parameter labels from comments will be replaced by 'label()'
sim_typical <- rxode2::rxSolve(
mod_typical,
events = events,
keep = c("cohort", "WT", "CRCL")
) |> as.data.frame()
#> ℹ omega/sigma items treated as zero: 'etalvc', 'etalq', 'etalcl'
#> Warning: multi-subject simulation without without 'omega'Replicate published figures
Zhao 2015 Figure 1 is a goodness-of-fit / NPDE / VPC panel from the original NONMEM fit; it cannot be reproduced from the packaged model because the original observed concentrations are not publicly available. The blocks below reproduce the two relationships in Figure 2 (typical-value teicoplanin clearance vs body weight; per-kg CL vs age band) using the packaged typical-value equations.
# Replicates Figure 2A of Zhao 2015: typical-value CL vs body weight at
# CRCL = 179 mL/min/1.73 m^2 (the cohort median used as reference).
wt_grid <- seq(5, 100, by = 0.5)
fig2a <- tibble::tibble(
WT = wt_grid,
cl_typ_L_per_h = 0.491 * (wt_grid / 27.1)^0.75
)
ggplot(fig2a, aes(WT, cl_typ_L_per_h)) +
geom_line() +
scale_x_continuous(breaks = seq(0, 100, by = 10)) +
labs(
x = "Body weight (kg)",
y = "Typical CL (L/h)",
title = "Figure 2A - Typical-value teicoplanin CL vs body weight",
caption = "Replicates Figure 2A of Zhao 2015 using CL = 0.491 * (WT/27.1)^0.75 at CRCL = 179 mL/min/1.73 m^2."
)
Zhao 2015 Results reports the median per-kg clearance by age band: “The medians of CLs were 0.028, 0.019 and 0.015 L h-1 kg-1 for infants, children and adolescents, respectively.” Using representative weights near the per-band median (10, 25, 55 kg), the packaged typical-value equations recover these per-kg clearances:
anchor <- tibble::tibble(
band = c("infant", "child", "adolescent"),
WT = c(10, 25, 55),
cl_paper_L_per_h_per_kg = c(0.028, 0.019, 0.015),
cl_model_L_per_h = round(0.491 * (c(10, 25, 55) / 27.1)^0.75, 3),
cl_model_L_per_h_per_kg = round(0.491 * (c(10, 25, 55) / 27.1)^0.75 / c(10, 25, 55), 3)
)
knitr::kable(anchor, caption = "Per-kg typical CL anchors - Zhao 2015 Results vs packaged model at CRCL = 179 mL/min/1.73 m^2.")| band | WT | cl_paper_L_per_h_per_kg | cl_model_L_per_h | cl_model_L_per_h_per_kg |
|---|---|---|---|---|
| infant | 10 | 0.028 | 0.232 | 0.023 |
| child | 25 | 0.019 | 0.462 | 0.018 |
| adolescent | 55 | 0.015 | 0.835 | 0.015 |
# Replicates Figure 2B of Zhao 2015: size-normalised CL vs CRCL.
# "Size" is defined as (WT/27.1)^0.75 per the Figure 2 caption.
crcl_grid <- seq(40, 470, by = 5)
fig2b <- tibble::tibble(
CRCL = crcl_grid,
size_normalized_CL_L_per_h = 0.491 * (crcl_grid / 179)^0.606
)
ggplot(fig2b, aes(CRCL, size_normalized_CL_L_per_h)) +
geom_line() +
labs(
x = "Creatinine clearance (mL/min/1.73 m^2; Schwartz formula)",
y = "Size-normalised typical CL (L/h)",
title = "Figure 2B - Size-normalised teicoplanin CL vs creatinine clearance",
caption = "Replicates Figure 2B of Zhao 2015 using CL_norm = 0.491 * (CRCL/179)^0.606."
)
Simulated concentration-time profile
The simulated stochastic concentration-time profile illustrates the spread of teicoplanin exposures across the three covariate cohorts at the paper’s standard 10 mg/kg/day regimen. Dashed lines mark the 10 mg/L trough target (Css,min lower bound) and the 30 mg/L upper bound the paper uses for overdose risk.
sim |>
dplyr::group_by(cohort, time) |>
dplyr::summarise(
Q05 = quantile(Cc, 0.05, na.rm = TRUE),
Q50 = quantile(Cc, 0.50, na.rm = TRUE),
Q95 = quantile(Cc, 0.95, na.rm = TRUE),
.groups = "drop"
) |>
ggplot(aes(time, Q50)) +
geom_ribbon(aes(ymin = Q05, ymax = Q95), alpha = 0.25) +
geom_line() +
geom_hline(yintercept = c(10, 30), linetype = "dashed", color = "grey40") +
facet_wrap(~ cohort, scales = "free_y") +
labs(
x = "Time post first dose (h)",
y = "Simulated teicoplanin Cc (mg/L)",
title = "Simulated teicoplanin concentration-time profile by virtual cohort",
caption = "10 mg/kg Q12H for three loading doses then 10 mg/kg QD maintenance, as a 5-minute IV injection. Dashed lines mark the Zhao 2015 Css,min reference window (10-30 mg/L)."
)
PKNCA validation
Zhao 2015 does not publish a single-dose NCA table, so the PKNCA
block below characterises steady-state NCA parameters over the final
24-hour dosing interval (168-192 h, after seven daily maintenance doses)
for each cohort. The treatment grouping is cohort, matching
the three virtual scenarios. Steady-state AUC(0,24)ss and Css,min can
then be compared against the paper’s target AUC of 750 mg.L/h and the
Css,min windows quoted in Discussion.
ss_start <- 168
ss_end <- 192
sim_nca <- sim |>
dplyr::filter(!is.na(Cc), time >= ss_start, time <= ss_end) |>
dplyr::select(id, time, Cc, cohort)
# Defensively guarantee a time-zero-of-the-interval row so PKNCA doesn't
# complain about the AUC range starting before the first measurement.
sim_nca <- dplyr::bind_rows(
sim_nca,
sim_nca |>
dplyr::distinct(id, cohort) |>
dplyr::left_join(
sim |>
dplyr::filter(time == ss_start) |>
dplyr::select(id, cohort, Cc),
by = c("id", "cohort")
) |>
dplyr::mutate(time = ss_start)
) |>
dplyr::distinct(id, cohort, time, .keep_all = TRUE) |>
dplyr::arrange(id, cohort, time)
dose_df <- events |>
dplyr::filter(evid == 1, time >= ss_start - 24, time < ss_end) |>
dplyr::select(id, time, amt, cohort)
conc_obj <- PKNCA::PKNCAconc(sim_nca, Cc ~ time | cohort + id,
concu = "mg/L", timeu = "hr")
dose_obj <- PKNCA::PKNCAdose(dose_df, amt ~ time | cohort + id,
doseu = "mg")
intervals <- data.frame(
start = ss_start,
end = ss_end,
cmax = TRUE,
tmax = TRUE,
cmin = TRUE,
auclast = TRUE,
cav = TRUE
)
nca_res <- PKNCA::pk.nca(
PKNCA::PKNCAdata(conc_obj, dose_obj, intervals = intervals)
)
nca_summary <- summary(nca_res)
knitr::kable(nca_summary, caption = "Simulated steady-state NCA parameters by virtual cohort (10 mg/kg Q12H loading x 3 then 10 mg/kg QD maintenance, NCA over the final 24-hour interval 168-192 h).")| Interval Start | Interval End | cohort | N | AUClast (hr*mg/L) | Cmax (mg/L) | Cmin (mg/L) | Tmax (hr) | Cav (mg/L) |
|---|---|---|---|---|---|---|---|---|
| 168 | 192 | adol_55kg_crcl180 | 80 | 576 [23.9] | 37.5 [18.7] | 15.5 [35.1] | 0.500 [0.500, 0.500] | 24.0 [23.9] |
| 168 | 192 | child_25kg_crcl180 | 80 | 495 [23.0] | 34.1 [16.4] | 12.8 [38.1] | 0.500 [0.500, 0.500] | 20.6 [23.0] |
| 168 | 192 | infant_10kg_crcl180 | 80 | 377 [30.8] | 29.3 [19.5] | 8.58 [57.2] | 0.500 [0.500, 0.500] | 15.7 [30.8] |
Comparison against published outcomes
Zhao 2015 reports several quantitative outcomes the packaged model can be cross-checked against:
Per-kg typical CL by age band - reproduced in the
per-kg-CL-anchorstable above. The packaged equations recover the paper’s 0.028 / 0.019 / 0.015 L/h/kg trichotomy without tuning.Target AUC for MRSA PK-PD breakpoint = 750 mg.L/h. The paper notes that the standard 10 mg/kg/day regimen achieves the target in only 5% of infants, 27% of children, and 31% of adolescents (Results; Figure 3 target-attainment plot). The cohort-level steady-state
auclast(AUC over the final 24-h dosing interval) in the PKNCA table above shows the same direction: median AUC sits well below 750 mg.L/h for infants and below or near 750 mg.L/h for children under the nominal 10 mg/kg/day regimen, confirming the paper’s conclusion that the dose must be increased to 18 / 14 / 12 mg/kg for the three age bands respectively.-
Patient-tailored dose formula. The patient-tailored daily dose per the paper (Discussion Eq. 8) is
daily dose (mg) = target AUC * CL_i = 750 * 0.491 * (WT/27.1)^0.75 * (CRCL/179)^0.606which reproduces 18 / 14 / 12 mg/kg as the band-specific recommendation for median-sized infants / children / adolescents at typical pediatric CRCL.
target_AUC <- 750 # mg.L/h
tailored_dose <- function(WT, CRCL) {
CL_i <- 0.491 * (WT / 27.1)^0.75 * (CRCL / 179)^0.606
target_AUC * CL_i
}
tailored <- tibble::tibble(
band = c("infant", "child", "adolescent"),
WT = c(10, 25, 55),
CRCL = c(180, 180, 180),
paper_mg_per_kg = c(18, 14, 12),
model_daily_mg = round(tailored_dose(c(10, 25, 55), 180), 0),
model_mg_per_kg = round(tailored_dose(c(10, 25, 55), 180) / c(10, 25, 55), 1)
)
knitr::kable(tailored, caption = "Patient-tailored daily dose recovered from the packaged model vs Zhao 2015 Results recommendation (target AUC 750 mg.L/h).")| band | WT | CRCL | paper_mg_per_kg | model_daily_mg | model_mg_per_kg |
|---|---|---|---|---|---|
| infant | 10 | 180 | 18 | 175 | 17.5 |
| child | 25 | 180 | 14 | 348 | 13.9 |
| adolescent | 55 | 180 | 12 | 628 | 11.4 |
Assumptions and deviations
-
CRCL units. Zhao 2015 Table 1 labels creatinine
clearance as “ml min-1” but the values were produced by the Schwartz
formula (Methods: “creatinine clearance (Schwartz formula)”), which
yields eGFR in mL/min/1.73 m^2 by construction. Median 178.9 with a
maximum of 464.1 mL/min is also consistent with the BSA-normalised eGFR
scale typical of pediatric Schwartz-formula values when serum creatinine
is low. The packaged model stores CRCL in mL/min/1.73 m^2 (canonical
units in
inst/references/covariate-columns.md) and thecovariateData[[CRCL]]$notesfield records the unit clarification. -
Fixed allometric exponents. The four allometric
exponents in the model (1 for Vc and Vp, 0.75 for Q and CL) were fixed a
priori per Results (“allometric coefficients of 0.75 for CL and Q, 1 for
V1 and V2”); the packaged
ini()wraps each infixed()to preserve that provenance. The CRCL exponent (0.606) was estimated and is therefore not wrapped infixed(). -
Dose regimen used in the virtual cohort. The
packaged virtual cohort uses the standard 10 mg/kg Q12H x 3 loading then
10 mg/kg QD maintenance regimen (Methods: “The initial dosing regimen
was 10 mg kg-1 every 12 h for three loading doses followed by
maintenance dose of 10 mg kg-1 once daily”). The dose-optimization
simulations in the paper use the same starting regimen and scale it up
to 12-18 mg/kg by age band; the packaged model reproduces both the
standard and the patient-tailored daily-dose formula via the
tailored_dose()helper shown above. -
IV injection treated as a 5-minute infusion. Zhao
2015 Methods states “intravenous injection over 3-5 min”; the packaged
simulation uses 5 min as the upper bound for reproducibility. Treating
the injection as a bolus (
rate = 0) produces near-identical NCA values for this 2-compartment model because the distribution half-life (Q / Vp = 0.341 / 25.2 = 0.014 h^-1, t1/2_dist ~ 51 h) is much longer than the 5-minute infusion duration. - Single-center French pediatric cohort. The model parameters reflect an 85-patient single-center cohort at Robert Debre Hospital in Paris. Race and ethnicity are not reported in the paper.
- No bone-marrow-transplant covariate. 34 of 85 patients had received a bone marrow transplant, but the source paper does not evaluate transplant status as a covariate. The packaged model carries no BMT covariate.
- Disease type was not retained. Zhao 2015 Methods evaluated the type of haematological disease (leukaemia vs lymphoma) on CL during forward selection and did not retain it. The packaged model omits it.
-
Bootstrap and external-validation results are documented but
not re-fit. Zhao 2015 reports a 500-replicate nonparametric
bootstrap with median estimates closely matching the point values in
Table 2, and external validation in an independent group of 15 children
(Bayesian estimation, r^2 = 0.99, mean PE 0.7%, mean APE 5.3%). The
packaged model uses the Table 2 point estimates directly; bootstrap
variability is recorded in the
population$notesfield for traceability.