Example: Inter-occasion variability (IOV)

This example extends the one-compartment oral warfarin model to account for occasion-to-occasion variability in clearance.

Tip

For a full IOV walkthrough, see Chapter 10 (IOV) in the ferx book.

When to use IOV

Use IOV when:

  • Subjects have data from multiple study periods (crossover designs, multiple visits)
  • You expect within-subject PK variability across periods larger than pure residual error
  • NONMEM models used OMEGA BLOCK SAME syntax for one or more parameters

Dataset

Add an integer occasion-index column (OCC) to the dataset:

ID,TIME,DV,EVID,AMT,CMT,MDV,OCC
1,0,.,1,100,1,1,1
1,1,9.49,0,.,.,0,1
1,2,14.42,0,.,.,0,1
1,3,17.56,0,.,.,0,1
1,24,.,1,100,1,1,2
1,25,10.1,0,.,.,0,2
1,26,8.2,0,.,.,0,2

Dose records and observation records in the same period share the same OCC value. The occasion index can be any positive integers; they do not need to be consecutive.

Option A — diagonal IOV (independent kappas)

[parameters]
  theta TVCL(0.2, 0.001, 10.0)
  theta TVV(10.0, 0.1, 500.0)
  theta TVKA(1.5, 0.01, 50.0)

  omega ETA_CL ~ 0.09    # between-subject variability in CL
  omega ETA_V  ~ 0.04
  omega ETA_KA ~ 0.30

  kappa KAPPA_CL ~ 0.01  # inter-occasion variability in CL

  sigma PROP_ERR ~ 0.02

[individual_parameters]
  CL = TVCL * exp(ETA_CL + KAPPA_CL)
  V  = TVV  * exp(ETA_V)
  KA = TVKA * exp(ETA_KA)

[structural_model]
  pk one_cpt_oral(cl=CL, v=V, ka=KA)

[error_model]
  DV ~ proportional(PROP_ERR)

[fit_options]
  method     = focei
  iov_column = OCC
  covariance = true

Key additions vs a standard model:

  1. kappa KAPPA_CL ~ 0.01 — declares IOV on CL with starting variance 0.01
  2. + KAPPA_CL in the CL expression — kappa enters just like a BSV eta
  3. iov_column = OCC — tells ferx which dataset column carries occasion labels

Option B — correlated IOV (block_kappa)

If IOV on CL and V are expected to covary across occasions:

block_kappa (KAPPA_CL, KAPPA_V) = [0.05, 0.01, 0.03]

The three values are the lower triangle of Ω_IOV:

  • 0.05 = Var(KAPPA_CL)
  • 0.01 = Cov(KAPPA_CL, KAPPA_V)
  • 0.03 = Var(KAPPA_V)
[individual_parameters]
  CL = TVCL * exp(ETA_CL + KAPPA_CL)
  V  = TVV  * exp(ETA_V  + KAPPA_V)
  KA = TVKA * exp(ETA_KA)

In R

library(ferx)
ex  <- ferx_example("warfarin_iov")
fit <- ferx_fit(ex$model, ex$data)
print(fit)
# Shows OMEGA_IOV  (inter-occasion variability) block alongside the standard OMEGA output

fit$omega_iov        # IOV omega matrix
fit$ebe_kappas       # per-subject, per-occasion kappa EBEs (list of lists)

Interpreting output

The print(fit) output gains a OMEGA_IOV (inter-occasion variability) block after the standard omega section. For Option B with off-diagonal correlations, a correlations sub-block follows the diagonal entries.

EBE kappas are returned in fit$ebe_kappas but are not yet emitted as columns in the sdtab CSV. Per-kappa shrinkage is computed and reported in the OMEGA_IOV section of print(fit) alongside the BSV shrinkage values.

Tips

  • Start with IOV on CL only — the most commonly occasion-sensitive parameter. Add IOV on other parameters only when the OFV improvement justifies it.
  • Compare OFV between BSV-only and IOV models: the difference is a likelihood-ratio test for the added IOV variance. For a variance parameter at the boundary (H₀: σ² = 0), the asymptotic null is a 50:50 mixture of a point mass at 0 and χ²₁.
  • SAEM supports IOV — use method = "saem" or a c("saem", "focei") chain for robust convergence on ill-conditioned datasets.

See also