lstparsR: Tidy Parsing of NONMEM Listing Files
Raban Heller
Dominik Selzer
Simeon Rüdesheim
Christiane Dings
Thorsten Lehr
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. Parsers return
NAfor unavailable optional quantities. Missing required parameter sections raise errors. For batch workflows,fetch_all()catches individual parser errors, warns, and returnsNULLfor those elements while retaining the other results.Tidiness. Parameter output is returned as tibbles with consistent, lowercase column names (
parameter,estimate,se,rse,shrinkage) ready for binding across runs withdplyrorpurrr.
The package recognizes FOCE-I, FOCE, FO, SAEM, IMP, IMPMAP, and Bayesian method headers. Output layout coverage is described below.
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 3.89e- 2 1.94e 1 5.08
#> 2 ETA2 0.255 4.63e- 2 1.82e 1 1.62
#> 3 ETA3 0.1 2 e+73 2 e76 100
#> 4 ETA4 0.1 1.99e+73 1.99e76 100
#> 5 ETA5 0.00001 6.85e+68 6.85e75 97.6
#> 6 ETA6 0.00001 NA NA 99.0
#> 7 ETA7 0.00001 NA NA 97.0Both 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 3.89e- 2 1.94e 1 5.1
#> 2 ETA2 0.255 4.63e- 2 1.82e 1 1.6
#> 3 ETA3 0.1 2 e+73 2 e76 100
#> 4 ETA4 0.1 1.99e+73 1.99e76 100
#> 5 ETA5 0.00001 6.85e+68 6.85e75 97.6
#> 6 ETA6 0.00001 NA NA 99
#> 7 ETA7 0.00001 NA NA 97SIGMA — 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, and
condition number are returned as NA. The parameter
estimates and OFV are still available.
path2 <- system.file("testdata", "theta_without_cov.lst", package = "lstparsR")
lst2 <- read_lst_file(path2)
summary(lst2)
#> <lst> NONMEM listing file
#> Lines : 34
#> Estimation method: FIRST ORDER CONDITIONAL ESTIMATION WITH INTERACTION
#> Covariance step : FALSE
fetch_thetas(lst2)
#> # A tibble: 12 × 4
#> parameter estimate se rse
#> <chr> <dbl> <dbl> <dbl>
#> 1 TH_1 34.1 NA NA
#> 2 TH_2 387000 NA NA
#> 3 TH_3 8.05 NA NA
#> 4 TH_4 1.78 NA NA
#> 5 TH_5 0.498 NA NA
#> 6 TH_6 0.362 NA NA
#> 7 TH_7 -0.171 NA NA
#> 8 TH_8 -0.0314 NA NA
#> 9 TH_9 -0.163 NA NA
#> 10 TH10 -0.23 NA NA
#> 11 TH11 0.00539 NA NA
#> 12 TH12 0.2 NA NA
fetch_condn(lst2)
#> [1] NABatch 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 |
Estimation Headers and Output Layouts
lstparsR automatically detects the estimation method from the
.lst file header. The following headers are recognized:
- 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
Numerical regression tests cover FOCE-I listings and controlled edge cases; FO listings have additional execution coverage. Recognizing a method header does not validate every layout or posterior summary from that method. The parsers expect the fixed-format result sections shown in the examples. Compare results with the original listing for unfamiliar layouts. Parsing does not validate the scientific model or its estimates.
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
- 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.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.5 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.2
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.7.3 cli_3.6.6 knitr_1.52 rlang_1.3.0
#> [5] xfun_0.61 stringi_1.8.9 otel_0.2.0 purrr_1.2.2
#> [9] textshaping_1.0.5 jsonlite_2.0.0 glue_1.8.1 backports_1.5.1
#> [13] htmltools_0.5.9 ragg_1.5.2 sass_0.4.10 rmarkdown_2.32
#> [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.6.1
#> [25] fs_2.1.0 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.5
#> [33] bslib_0.12.0 checkmate_2.3.4 tools_4.6.1 pkgdown_2.2.1
#> [37] cachem_1.1.0 desc_1.4.3