lstparsR: Tidy Parsing of NONMEM Listing Files
Source:vignettes/lstparsR-guide.Rmd
lstparsR-guide.RmdIntroduction
Population pharmacokinetic and pharmacodynamic (PK/PD) modelling with
NONMEM produces listing files (.lst) that contain parameter
estimates, standard errors, objective function values, eigenvalues, and
shrinkage statistics in a structured but complex text format. Extracting
these quantities for downstream analysis — model comparison tables,
forest plots, covariate analyses — typically requires manual copy-paste
or ad-hoc scripts that are fragile and error-prone.
lstparsR provides a clean, validated interface for
reading .lst files and returning tidy data frames. It is
designed with two goals:
Robustness. All parsers return
NAfor unavailable quantities rather than raising errors. This makes the package safe for batch workflows where some NONMEM runs may have failed or been terminated early.Tidiness. All output is returned as tibbles with consistent, lowercase column names (
parameter,estimate,se,rse,shrinkage) ready for binding across runs withdplyrorpurrr.
The package supports all major NONMEM estimation methods: FOCE-I, FOCE, FO, SAEM, IMP, IMPMAP, and Bayesian analysis.
Installation
Install the development version from GitHub:
# install.packages("remotes")
remotes::install_github("Clinical-Pharmacy-Saarland-University/lstparsR")Quick Start
library(lstparsR)
path <- system.file("testdata", "full_cov.lst", package = "lstparsR")
lst <- read_lst_file(path)
lst
#> <lst> NONMEM listing file: 1321 linesReading Listing Files
read_lst_file() reads a .lst file into an
S3 object of class "lst". This is simply a character vector
(one element per line) with the class attribute attached. All
fetch_* functions require this class as input.
lst <- read_lst_file(
system.file("testdata", "full_cov.lst", package = "lstparsR")
)
summary(lst)
#> <lst> NONMEM listing file
#> Lines : 1321
#> Estimation method: FIRST ORDER CONDITIONAL ESTIMATION WITH INTERACTION
#> Covariance step : TRUEExtracting Parameters
THETA — Fixed Effects
fetch_thetas() extracts the THETA parameter estimates
from the FINAL PARAMETER ESTIMATE section. When the covariance
step was completed, standard errors (SE) and relative standard errors
(RSE, in percent) are also reported.
fetch_thetas(lst)
#> # A tibble: 12 × 4
#> parameter estimate se rse
#> <chr> <dbl> <dbl> <dbl>
#> 1 TH_1 34.1 3.37e+ 0 9.88e 0
#> 2 TH_2 387000 5.41e+ 7 1.40e 4
#> 3 TH_3 8.05 5.2 e- 1 6.46e 0
#> 4 TH_4 1.78 1.49e- 1 8.37e 0
#> 5 TH_5 0.498 2.78e- 2 5.58e 0
#> 6 TH_6 0.362 4.81e- 1 1.33e 2
#> 7 TH_7 -0.171 1.35e- 1 7.89e 1
#> 8 TH_8 -0.0314 2.69e- 1 8.57e 2
#> 9 TH_9 -0.163 2.78e- 1 1.71e 2
#> 10 TH10 -0.23 1.88e- 1 8.17e 1
#> 11 TH11 0.00539 1.98e- 2 3.67e 2
#> 12 TH12 0.2 1.90e+74 9.50e76The digits argument rounds RSE values:
fetch_thetas(lst, digits = 1)
#> # A tibble: 12 × 4
#> parameter estimate se rse
#> <chr> <dbl> <dbl> <dbl>
#> 1 TH_1 34.1 3.37e+ 0 9.9 e 0
#> 2 TH_2 387000 5.41e+ 7 1.40e 4
#> 3 TH_3 8.05 5.2 e- 1 6.5 e 0
#> 4 TH_4 1.78 1.49e- 1 8.4 e 0
#> 5 TH_5 0.498 2.78e- 2 5.6 e 0
#> 6 TH_6 0.362 4.81e- 1 1.33e 2
#> 7 TH_7 -0.171 1.35e- 1 7.89e 1
#> 8 TH_8 -0.0314 2.69e- 1 8.57e 2
#> 9 TH_9 -0.163 2.78e- 1 1.71e 2
#> 10 TH10 -0.23 1.88e- 1 8.17e 1
#> 11 TH11 0.00539 1.98e- 2 3.67e 2
#> 12 TH12 0.2 1.90e+74 9.50e76OMEGA — Random Effects
fetch_etas() extracts the diagonal of the OMEGA
covariance matrix (variance of inter-individual random effects). ETA
shrinkage is included when reported by NONMEM.
fetch_etas(lst)
#> # A tibble: 7 × 5
#> parameter estimate se rse shrinkage
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 ETA1 0.2 0.0389 19.4 NA
#> 2 ETA2 0.255 0.0463 18.2 NA
#> 3 ETA3 0.1 73 73000 NA
#> 4 ETA4 0.1 73 73000 NA
#> 5 ETA5 0.00001 68 680000000 NA
#> 6 ETA6 0.00001 NA NA NA
#> 7 ETA7 0.00001 NA NA NABoth RSE and shrinkage rounding can be controlled independently:
fetch_etas(lst, digits = 1, shk_digits = 1)
#> # A tibble: 7 × 5
#> parameter estimate se rse shrinkage
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 ETA1 0.2 0.0389 19.4 NA
#> 2 ETA2 0.255 0.0463 18.2 NA
#> 3 ETA3 0.1 73 73000 NA
#> 4 ETA4 0.1 73 73000 NA
#> 5 ETA5 0.00001 68 680000000 NA
#> 6 ETA6 0.00001 NA NA NA
#> 7 ETA7 0.00001 NA NA NASIGMA — Residual Error
fetch_sigmas() extracts the diagonal of the SIGMA
covariance matrix (variance of residual error terms).
fetch_sigmas(lst)
#> # A tibble: 2 × 4
#> parameter estimate se rse
#> <chr> <dbl> <dbl> <dbl>
#> 1 EPS1 0.0769 0.00434 5.64
#> 2 EPS2 0.123 0.199 162.Objective Function Value
fetch_ofv() extracts the OFV from the
#OBJV: line. For failed or early-terminated runs, it falls
back to the workflow footer (OFV = ...) if present.
Condition Number
fetch_condn() computes the condition number of the
correlation matrix of parameter estimates as the ratio of the largest to
the smallest eigenvalue. Condition numbers above 1000 suggest numerical
instability in the estimation.
fetch_condn(lst)
#> [1] 23.30882
fetch_condn(lst, digits = 1)
#> [1] 23.3All Parameters at Once
fetch_all() is a convenience wrapper that calls every
parser and returns a named list. Individual failures are caught and
returned as NULL with a warning, so one problematic section
does not abort the entire call.
result <- fetch_all(lst)
result$thetas
#> # A tibble: 12 × 4
#> parameter estimate se rse
#> <chr> <dbl> <dbl> <dbl>
#> 1 TH_1 34.1 3.37e+ 0 9.88e 0
#> 2 TH_2 387000 5.41e+ 7 1.40e 4
#> 3 TH_3 8.05 5.2 e- 1 6.46e 0
#> 4 TH_4 1.78 1.49e- 1 8.37e 0
#> 5 TH_5 0.498 2.78e- 2 5.58e 0
#> 6 TH_6 0.362 4.81e- 1 1.33e 2
#> 7 TH_7 -0.171 1.35e- 1 7.89e 1
#> 8 TH_8 -0.0314 2.69e- 1 8.57e 2
#> 9 TH_9 -0.163 2.78e- 1 1.71e 2
#> 10 TH10 -0.23 1.88e- 1 8.17e 1
#> 11 TH11 0.00539 1.98e- 2 3.67e 2
#> 12 TH12 0.2 1.90e+74 9.50e76
result$ofv
#> [1] 8986.318
result$condn
#> [1] 23.30882Handling Runs Without a Covariance Step
When NONMEM did not complete the covariance step, SE, RSE, shrinkage,
and condition number are returned as NA. The parameter
estimates and OFV are still available.
path2 <- system.file("testdata", "theta_no_cov.lst", package = "lstparsR")
lst2 <- read_lst_file(path2)
summary(lst2)
#> <lst> NONMEM listing file
#> Lines : 1246
#> Estimation method: FIRST ORDER CONDITIONAL ESTIMATION WITH INTERACTION
#> Covariance step : TRUE
fetch_thetas(lst2)
#> # A tibble: 12 × 4
#> parameter estimate se rse
#> <chr> <dbl> <dbl> <dbl>
#> 1 TH_1 34.1 3.37e+ 0 9.88e 0
#> 2 TH_2 387000 5.41e+ 7 1.40e 4
#> 3 TH_3 8.05 5.2 e- 1 6.46e 0
#> 4 TH_4 1.78 1.49e- 1 8.37e 0
#> 5 TH_5 0.498 2.78e- 2 5.58e 0
#> 6 TH_6 0.362 4.81e- 1 1.33e 2
#> 7 TH_7 -0.171 1.35e- 1 7.89e 1
#> 8 TH_8 -0.0314 2.69e- 1 8.57e 2
#> 9 TH_9 -0.163 2.78e- 1 1.71e 2
#> 10 TH10 -0.23 1.88e- 1 8.17e 1
#> 11 TH11 0.00539 1.98e- 2 3.67e 2
#> 12 TH12 0.2 1.90e+74 9.50e76
fetch_condn(lst2)
#> [1] 23.30882Batch Processing
A common pattern is to parse many .lst files from a
model development workflow:
library(purrr)
files <- list.files("models/", pattern = "\\.lst$", full.names = TRUE)
results <- map(files, \(f) {
lst <- read_lst_file(f)
fetch_all(lst)
})
# Combine all THETA tables with run identifier
all_thetas <- map_dfr(results, "thetas", .id = "run")
# Extract OFV for model comparison
ofvs <- map_dbl(results, "ofv")Since fetch_all() uses purrr::safely()
internally, failed runs produce NULL elements rather than
stopping the pipeline.
Function Reference
| Function | Description |
|---|---|
read_lst_file() |
Read a .lst file into an lst object |
fetch_thetas() |
THETA estimates with SE and RSE |
fetch_etas() |
OMEGA diagonal with SE, RSE, and ETA shrinkage |
fetch_sigmas() |
SIGMA diagonal with SE and RSE |
fetch_ofv() |
Objective function value (with footer fallback) |
fetch_condn() |
Condition number from eigenvalues |
fetch_all() |
Run all parsers; return named list |
run_app() |
Launch interactive Shiny application |
Supported Estimation Methods
lstparsR automatically detects the estimation method from the
.lst file header. The following methods are supported:
- First Order (FO)
- First Order Conditional Estimation (FOCE)
- First Order Conditional Estimation with Interaction (FOCE-I)
- Stochastic Approximation Expectation-Maximization (SAEM)
- Importance Sampling (IMP)
- Importance Sampling Assisted by Mode A Posteriori (IMPMAP)
- Markov Chain Monte Carlo Bayesian Analysis
Interactive Shiny Application
For interactive exploration, lstparsR includes a Shiny application that can be launched with:
lstparsR::run_app()The application provides:
- Multi-file upload with instant parsing
- Overview dashboard with parse status summary
- Sortable tables for THETA, OMEGA, and SIGMA parameters
- OFV and condition number summary
- Download buttons for CSV and RDS export
Session Info
sessionInfo()
#> R version 4.5.3 (2026-03-11)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
#> [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
#> [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
#> [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] lstparsR_0.1.0
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.7.2 cli_3.6.5 knitr_1.51 rlang_1.1.7
#> [5] xfun_0.57 stringi_1.8.7 otel_0.2.0 purrr_1.2.1
#> [9] textshaping_1.0.5 jsonlite_2.0.0 glue_1.8.0 backports_1.5.0
#> [13] htmltools_0.5.9 ragg_1.5.2 sass_0.4.10 rmarkdown_2.31
#> [17] tibble_3.3.1 evaluate_1.0.5 jquerylib_0.1.4 fastmap_1.2.0
#> [21] yaml_2.3.12 lifecycle_1.0.5 stringr_1.6.0 compiler_4.5.3
#> [25] fs_2.0.1 pkgconfig_2.0.3 systemfonts_1.3.2 digest_0.6.39
#> [29] R6_2.6.1 utf8_1.2.6 pillar_1.11.1 magrittr_2.0.4
#> [33] bslib_0.10.0 checkmate_2.3.4 tools_4.5.3 pkgdown_2.2.0
#> [37] cachem_1.1.0 desc_1.4.3