--- title: "Introduction to `pmxpartab`" author: "Benjamin Rich" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: css: vignette.css toc: true vignette: > %\VignetteIndexEntry{Introduction to `pmxpartab`} %\VignetteEngine{knitr::rmarkdown} %\VignetteDepends{yaml} %\VignetteEncoding{UTF-8} --- ```{r echo=FALSE, message=FALSE, warning=FALSE, results='hide'} library(pmxpartab, quietly=TRUE) ``` ## Introduction This R package produces nice looking parameter tables for pharmacometric modeling results with ease. It is completely agnostic to the modeling software that was used. ## Usage The creation of the parameter table proceeds in 2 steps: 1. Generate an intermediate `data.frame` from a list of outputs and metadata. 2. Genreate an HTML table from the intermediate `data.frame`. For the first step, the inputs are: 1. Model outputs (parameter estimates, standard errors, etc.) 2. Metadata, describing the outputs (labels, units, transformations, etc.) To keep things generic, both the model outputs and metadata must be provided as R lists (it is a separate problem to extract the outputs from the modeling software into the required list format, although the package does include an auxiliary function to help deal specifically with NONMEM outputs). For illustration, we will use a YAML description of the outputs and metadata, which can easily be read into R. First, the outputs: ```{r} library(yaml) outputs <- yaml.load(" est: CL: 0.482334 VC: 0.0592686 nCL: 0.315414 nVC: 0.536025 ERRP: 0.0508497 se: CL: 0.0138646 VC: 0.0055512 nCL: 0.0188891 nVC: 0.0900352 ERRP: 0.0018285 fixed: CL: no VC: no nCL: no nVC: no ERRP: no shrinkage: nCL: 9.54556 nVC: 47.8771 ") ``` We see that the outputs are split into separate sections: `est` for estimates, `se` for standard errors, `fixed` for indicating which parameters were fixed rather than estimated, `shrinkage` for shrinkage estimates. Now, the metadata: ```{r} meta <- yaml.load(" parameters: - name: CL label: 'Clearance' units: 'L/h' type: Structural - name: VC label: 'Volume' units: 'L' type: Structural trans: 'exp' - name: nCL label: 'On Clearance' type: IIV trans: 'SD (CV%)' - name: nVC label: 'On Volume' type: IIV trans: 'SD (CV%)' - name: ERRP label: 'Proportional Error' units: '%' type: RUV trans: '%' ") ``` Here, the first important thing is the `name`, which must match the names of the parameters in the outputs. Then, we have some optional attributes: a descriptive `label`, the `units` if applicable, a transformation `trans`, and a `type`. Putting this all together, we can produce a `data.frame` like this: ```{r} parframe <- pmxparframe(outputs, meta) parframe ``` Finally, our nicely formatted table looks like this: ```{r} pmxpartab(parframe) ``` We can also do this in one shot, and add footnotes as well: ```{r} footnote <- c( "CI=confidence interval; RSE=relative standard error.", "Source: run001") pmxpartab(pmxparframe(outputs, meta), footnote=footnote) ``` It is also possible to use the pipe syntax: ```{r} outputs |> pmxparframe(meta) |> pmxpartab(footnote=footnote) ``` ## Random effects and off-diagonal elements There is some debate on the best way to present the random effects from a mixed-effects model (i.e., the parameter(s) that describe the (joint) distribution of the random effects, which are typically assumed to follow a multivariate normal distribution). Some modelers are accustomed to seeing the variances and covariances, while others (such as me) prefer the standard deviations and correlations. In the standard log-normal case, diagonal elements are often presented in the form of their (geometric) coefficient of variation, which can be derived from the standard deviation $ω$ by $\sqrt{e^{ω^2}-1}$, as is typically shown as a percentage. In any case, `pmxpartab` is agnostic to this choice, and gives freedom and flexibility in this respect. In one version (call it the _flat_ version), all estimates are at the top level of the components `est`, `se` and `fixed`. Here is an example: ```{r} outputs <- yaml.load(" est: nCL: 3.95926E-01 nVC: 1.42749E+00 nCL_nVC: 8.45393E-02 se: nCL: 9.57069E-03 nVC: 4.62152E-02 nCL_nVC: 4.26648E-02 ") meta <- yaml.load(" parameters: - name: 'nCL' label: 'On CL' type: IIV - name: 'nVC' label: 'On Vc' type: IIV - name: 'nCL_nVC' label: 'Correlation CL-Vc' type: IIV ") outputs |> pmxparframe(meta) |> pmxpartab() ``` In another version (call it the _structured_ version), between-individual random effect parameters are contained in sub-components of `est`, `se` and `fixed`: - `om` contains the standard deviations as a named vector - `om_cov` contains the variance-covariance matrix - `om_cor` contains the correlation matrix, with standard deviations on the diagonal Here is an example: ```{r} outputs <- list( est = list( om = c(nCL=3.95926E-01, nVC=1.42749E+00), om_cov = matrix(c(1.56758E-01, 4.77799E-02, 4.77799E-02, 2.03772E+00), 2, 2), om_cor = matrix(c(3.95926E-01, 8.45393E-02, 8.45393E-02, 1.42749E+00), 2, 2)), se = list( om = c(nCL=9.57069E-03, nVC=4.62152E-02), om_cov = matrix(c(7.57858E-03, 2.47183E-02, 2.47183E-02, 1.31943E-01), 2, 2), om_cor = matrix(c(9.57069E-03, 4.26648E-02, 4.26648E-02, 4.62152E-02), 2, 2))) meta <- yaml.load(" parameters: - name: 'om_cov(nCL,nCL)' label: 'Variance log(CL)' type: IIV - name: 'om_cov(nVC,nVC)' label: 'Variance log(Vc)' type: IIV - name: 'om_cor(nCL,nCL)' label: 'SD log(CL)' type: IIV - name: 'om_cor(nVC,nVC)' label: 'SD log(Vc)' type: IIV - name: 'om_cov(nCL,nVC)' label: 'Covariance log(CL)-log(Vc)' type: IIV - name: 'om_cor(nCL,nVC)' label: 'Correlation log(CL)-log(Vc)' type: IIV ") outputs |> pmxparframe(meta) |> pmxpartab() ``` ## Bootstrap results TBD