using Dates
using Pumas
using PumasUtilities
using CairoMakie
using DataFramesMeta
using CSV
using PharmaDatasets

Covariate Models
Some functions in this tutorial are only available after you load the PumasUtilities
package.
In this tutorial we’ll cover a workflow around covariate model building. You’ll learn how to:
- include covariates in your model
- parse data with covariates
- understand the difference between constant and time-varying covariates
- handle continuous and categorical covariates
- deal with missing data in your covariates
- deal with categorical covariates
1 nlme_sample
Dataset
For this tutorial we’ll use the nlme_sample
dataset from PharmaDatasets.jl
:
= dataset("nlme_sample", String)
pkfile = CSV.read(pkfile, DataFrame; missingstring = ["NA", ""])
pkdata first(pkdata, 5)
Row | ID | TIME | DV | AMT | EVID | CMT | RATE | WT | AGE | SEX | CRCL | GROUP | ROUTE | DURATION | OCC |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Int64 | Float64 | Float64? | Int64? | Int64 | Int64? | Int64 | Int64 | Int64 | String1 | Int64 | String7 | Float64 | Int64? | Int64 | |
1 | 1 | 0.0 | missing | 1000 | 1 | 1 | 500 | 90 | 47 | M | 75 | 1000 mg | Inf | 2 | 1 |
2 | 1 | 0.001 | 0.0667231 | missing | 0 | missing | 0 | 90 | 47 | M | 75 | 1000 mg | Inf | missing | 1 |
3 | 1 | 1.0 | 112.817 | missing | 0 | missing | 0 | 90 | 47 | M | 75 | 1000 mg | Inf | missing | 1 |
4 | 1 | 2.0 | 224.087 | missing | 0 | missing | 0 | 90 | 47 | M | 75 | 1000 mg | Inf | missing | 1 |
5 | 1 | 4.0 | 220.047 | missing | 0 | missing | 0 | 90 | 47 | M | 75 | 1000 mg | Inf | missing | 1 |
The nlme_sample
dataset has different missing values as the standard datasets in the PharmaDatasets.jl
. That’s why we are first getting a String
representation of the dataset as a CSV file as pkfile
variable. Then, we use it to customize the missingstring
keyword argument inside CSV.read
function in order to have a working DataFrame
for the nlme_sample
dataset.
If you want to know more about data wrangling and how to read and write data in different formats, please check out the Data Wrangling Tutorials at tutorials.pumas.ai
.
As you can see, the nlme_sample
dataset has the standard PK dataset columns such as :ID
, :TIME
, :DV
, :AMT
, :EVID
and :CMT
. The dataset also contains the following list of covariates:
:WT
: subject weight in kilograms:SEX
: subject sex, either"F"
or"M"
:CRCL
: subject creatinine clearance:GROUP
: subject dosing group, either"500 mg"
,"750 mg"
, or"1000 mg"
And we’ll learn how to include them in our Pumas modeling workflows.
describe(pkdata, :mean, :std, :nunique, :first, :last, :eltype)
Row | variable | mean | std | nunique | first | last | eltype |
---|---|---|---|---|---|---|---|
Symbol | Union… | Union… | Union… | Any | Any | Type | |
1 | ID | 15.5 | 8.661 | 1 | 30 | Int64 | |
2 | TIME | 82.6527 | 63.2187 | 0.0 | 168.0 | Float64 | |
3 | DV | 157.315 | 110.393 | missing | missing | Union{Missing, Float64} | |
4 | AMT | 750.0 | 204.551 | 1000 | 500 | Union{Missing, Int64} | |
5 | EVID | 0.307692 | 0.461835 | 1 | 1 | Int64 | |
6 | CMT | 1.0 | 0.0 | 1 | 1 | Union{Missing, Int64} | |
7 | RATE | 115.385 | 182.218 | 500 | 250 | Int64 | |
8 | WT | 81.6 | 11.6051 | 90 | 96 | Int64 | |
9 | AGE | 40.0333 | 11.6479 | 47 | 56 | Int64 | |
10 | SEX | 2 | M | F | String1 | ||
11 | CRCL | 72.5667 | 26.6212 | 75 | 90 | Int64 | |
12 | GROUP | 3 | 1000 mg | 500 mg | String7 | ||
13 | ROUTE | Inf | NaN | Inf | Inf | Float64 | |
14 | DURATION | 2.0 | 0.0 | 2 | 2 | Union{Missing, Int64} | |
15 | OCC | 4.15385 | 2.62836 | 1 | 8 | Int64 |
As you can see, all these covariates are constant. That means, they do not vary over time. We’ll also cover time-varying covariates later in this tutorial.
2 Step 1 - Parse Data into a Population
The first step in our covariate model building workflow is to parse data into a Population
. This is accomplished with the read_pumas
function. Here we are to use the covariates
keyword argument to pass a vector of column names to be parsed as covariates:
= read_pumas(
pop
pkdata;= :ID,
id = :TIME,
time = :AMT,
amt = [:WT, :AGE, :SEX, :CRCL, :GROUP],
covariates = [:DV],
observations = :CMT,
cmt = :EVID,
evid = :RATE,
rate )
Population
Subjects: 30
Covariates: WT, AGE, SEX, CRCL, GROUP
Observations: DV
Due to Pumas’ dynamic workflow capabilities, we only need to define our Population
once. That is, we tell read_pumas
to parse all the covariates available, even if we will be using none or a subset of those in our models.
This is a feature that highly increases workflow efficiency in developing and fitting models.
3 Step 2 - Base Model
The second step of our covariate model building workflow is to develop a base model, i.e., a model without any covariate effects on its parameters. This represents the null model against which covariate models can be tested after checking if covariate inclusion is helpful in our model.
Let’s create a combined-error simple 2-compartment base model:
= @model begin
base_model @param begin
∈ RealDomain(; lower = 0)
tvcl ∈ RealDomain(; lower = 0)
tvvc ∈ RealDomain(; lower = 0)
tvq ∈ RealDomain(; lower = 0)
tvvp ∈ PDiagDomain(2)
Ω ∈ RealDomain(; lower = 0)
σ_add ∈ RealDomain(; lower = 0)
σ_prop end
@random begin
~ MvNormal(Ω)
η end
@pre begin
= tvcl * exp(η[1])
CL = tvvc * exp(η[2])
Vc = tvq
Q = tvvp
Vp end
@dynamics Central1Periph1
@derived begin
:= @. Central / Vc
cp ~ @. Normal(cp, sqrt(cp^2 * σ_prop^2 + σ_add^2))
DV end
end
PumasModel
Parameters: tvcl, tvvc, tvq, tvvp, Ω, σ_add, σ_prop
Random effects: η
Covariates:
Dynamical system variables: Central, Peripheral
Dynamical system type: Closed form
Derived: DV
Observed: DV
And fit it accordingly:
= (;
iparams_base_model = 5,
tvvc = 0.02,
tvcl = 0.01,
tvq = 10,
tvvp = Diagonal([0.01, 0.01]),
Ω = 0.1,
σ_add = 0.1,
σ_prop )
(tvvc = 5,
tvcl = 0.02,
tvq = 0.01,
tvvp = 10,
Ω = [0.01 0.0; 0.0 0.01],
σ_add = 0.1,
σ_prop = 0.1,)
= fit(base_model, pop, iparams_base_model, FOCE()) fit_base_model
[ Info: Checking the initial parameter values.
[ Info: The initial negative log likelihood and its gradient are finite. Check passed.
Iter Function value Gradient norm
0 8.300164e+03 4.360770e+03
* time: 0.025621891021728516
1 3.110315e+03 9.706222e+02
* time: 1.0510759353637695
2 2.831659e+03 7.817006e+02
* time: 1.2130820751190186
3 2.405281e+03 2.923696e+02
* time: 1.2819879055023193
4 2.370406e+03 3.032286e+02
* time: 1.3345019817352295
5 2.313631e+03 3.126188e+02
* time: 1.3888940811157227
6 2.263986e+03 2.946697e+02
* time: 1.437803030014038
7 2.160182e+03 1.917599e+02
* time: 1.5090949535369873
8 2.112467e+03 1.588288e+02
* time: 1.5737171173095703
9 2.090339e+03 1.108334e+02
* time: 1.618088960647583
10 2.078171e+03 8.108027e+01
* time: 1.6669321060180664
11 2.074517e+03 7.813928e+01
* time: 1.7105250358581543
12 2.066270e+03 7.044632e+01
* time: 1.7542519569396973
13 2.049660e+03 1.062584e+02
* time: 1.8558480739593506
14 2.021965e+03 1.130570e+02
* time: 1.8961169719696045
15 1.994936e+03 7.825801e+01
* time: 1.935425043106079
16 1.979337e+03 5.318263e+01
* time: 1.9743189811706543
17 1.972141e+03 6.807046e+01
* time: 2.0127758979797363
18 1.967973e+03 7.896361e+01
* time: 2.050477981567383
19 1.962237e+03 8.343757e+01
* time: 2.0900189876556396
20 1.952791e+03 5.565304e+01
* time: 2.130244016647339
21 1.935857e+03 3.923284e+01
* time: 2.171376943588257
22 1.926254e+03 5.749643e+01
* time: 2.211822032928467
23 1.922144e+03 4.306225e+01
* time: 2.2494490146636963
24 1.911566e+03 4.810496e+01
* time: 2.2914700508117676
25 1.906464e+03 4.324267e+01
* time: 2.336946964263916
26 1.905339e+03 1.207954e+01
* time: 2.398267984390259
27 1.905092e+03 1.093479e+01
* time: 2.43369197845459
28 1.904957e+03 1.057034e+01
* time: 2.4687340259552
29 1.904875e+03 1.060882e+01
* time: 2.5022690296173096
30 1.904459e+03 1.031525e+01
* time: 2.5377860069274902
31 1.903886e+03 1.041179e+01
* time: 2.5754880905151367
32 1.903313e+03 1.135672e+01
* time: 2.6124370098114014
33 1.903057e+03 1.075683e+01
* time: 2.647097110748291
34 1.902950e+03 1.091295e+01
* time: 2.682292938232422
35 1.902887e+03 1.042409e+01
* time: 2.716481924057007
36 1.902640e+03 9.213043e+00
* time: 2.7520220279693604
37 1.902364e+03 9.519321e+00
* time: 2.7880680561065674
38 1.902156e+03 5.590984e+00
* time: 2.8246970176696777
39 1.902094e+03 1.811898e+00
* time: 2.866909980773926
40 1.902086e+03 1.644722e+00
* time: 2.9269349575042725
41 1.902084e+03 1.653520e+00
* time: 2.960542917251587
42 1.902074e+03 1.720184e+00
* time: 2.994633913040161
43 1.902055e+03 2.619061e+00
* time: 3.0286879539489746
44 1.902015e+03 3.519729e+00
* time: 3.0628750324249268
45 1.901962e+03 3.403372e+00
* time: 3.098323106765747
46 1.901924e+03 1.945644e+00
* time: 3.131861925125122
47 1.901914e+03 6.273342e-01
* time: 3.1654140949249268
48 1.901913e+03 5.374557e-01
* time: 3.198422908782959
49 1.901913e+03 5.710007e-01
* time: 3.230139970779419
50 1.901913e+03 6.091390e-01
* time: 3.262113094329834
51 1.901912e+03 6.692417e-01
* time: 3.2949130535125732
52 1.901909e+03 7.579620e-01
* time: 3.330374002456665
53 1.901903e+03 8.798211e-01
* time: 3.366763114929199
54 1.901889e+03 1.002981e+00
* time: 3.4236209392547607
55 1.901864e+03 1.495512e+00
* time: 3.4584569931030273
56 1.901837e+03 1.664621e+00
* time: 3.491044044494629
57 1.901819e+03 8.601118e-01
* time: 3.5245680809020996
58 1.901815e+03 4.525470e-02
* time: 3.5580921173095703
59 1.901815e+03 1.294280e-02
* time: 3.590919017791748
60 1.901815e+03 2.876568e-03
* time: 3.620661973953247
61 1.901815e+03 2.876568e-03
* time: 3.705904960632324
62 1.901815e+03 2.876568e-03
* time: 3.7934229373931885
FittedPumasModel
Successful minimization: true
Likelihood approximation: FOCE
Likelihood Optimizer: BFGS
Dynamical system type: Closed form
Log-likelihood value: -1901.815
Number of subjects: 30
Number of parameters: Fixed Optimized
0 8
Observation records: Active Missing
DV: 540 0
Total: 540 0
---------------------
Estimate
---------------------
tvcl 0.1542
tvvc 4.5856
tvq 0.042341
tvvp 3.7082
Ω₁,₁ 0.26467
Ω₂,₂ 0.10627
σ_add 0.032183
σ_prop 0.061005
---------------------
4 Step 3 - Covariate Model
The third step of our covariate model building workflow is to actually develop one or more covariate models. Let’s develop three covariate models:
- allometric scaling based on weight
- clearance effect based on creatinine clearance
- separated error model based on sex
To include covariates in a Pumas model we need to first include them in the @covariates
block. Then, we are free to use them inside the @pre
block
Here’s our covariate model with allometric scaling based on weight:
When building covariate models, unlike in NONMEM, it is highly recommended to derive covariates or perform any required transformations or scaling as a data wrangling step and pass the derived/transformed into read_pumas
as a covariate. In this particular case, it is easy to create two columns in the original data as:
@rtransform! pkdata :ASWT_CL = (:WT / 70)^0.75
@rtransform! pkdata :ASWT_Vc = (:WT / 70)
Then, you bring these covariates into read_pumas
and use them directly on CL
and Vc
. This will avoid computations of your transformations during the model fit.
= @model begin
covariate_model_wt @param begin
∈ RealDomain(; lower = 0)
tvcl ∈ RealDomain(; lower = 0)
tvvc ∈ RealDomain(; lower = 0)
tvq ∈ RealDomain(; lower = 0)
tvvp ∈ PDiagDomain(2)
Ω ∈ RealDomain(; lower = 0)
σ_add ∈ RealDomain(; lower = 0)
σ_prop end
@random begin
~ MvNormal(Ω)
η end
@covariates begin
WTend
@pre begin
= tvcl * (WT / 70)^0.75 * exp(η[1])
CL = tvvc * (WT / 70) * exp(η[2])
Vc = tvq
Q = tvvp
Vp end
@dynamics Central1Periph1
@derived begin
:= @. Central / Vc
cp ~ @. Normal(cp, sqrt(cp^2 * σ_prop^2 + σ_add^2))
DV end
end
PumasModel
Parameters: tvcl, tvvc, tvq, tvvp, Ω, σ_add, σ_prop
Random effects: η
Covariates: WT
Dynamical system variables: Central, Peripheral
Dynamical system type: Closed form
Derived: DV
Observed: DV
Once we included the WT
covariate in the @covariates
block we can use the WT
values inside the @pre
block. For both clearance (CL
) and volume of the central compartment (Vc
), we are allometric scaling by the WT
value by the mean weight 70
and, in the case of CL
using an allometric exponent with value 0.75
.
Let’s fit our covariate_model_wt
. Notice that we have not added any new parameters inside the @param
block, thus, we can use the same iparams_base_model
initial parameters values’ list:
= fit(covariate_model_wt, pop, iparams_base_model, FOCE()) fit_covariate_model_wt
[ Info: Checking the initial parameter values.
[ Info: The initial negative log likelihood and its gradient are finite. Check passed.
Iter Function value Gradient norm
0 7.695401e+03 4.898919e+03
* time: 6.890296936035156e-5
1 2.846050e+03 1.128657e+03
* time: 0.08052682876586914
2 2.472982e+03 7.008264e+02
* time: 0.13461995124816895
3 2.180690e+03 2.312704e+02
* time: 0.18978190422058105
4 2.125801e+03 1.862929e+02
* time: 0.23441481590270996
5 2.103173e+03 1.320946e+02
* time: 0.349808931350708
6 2.091136e+03 1.103035e+02
* time: 0.38991284370422363
7 2.081443e+03 1.091133e+02
* time: 0.42706894874572754
8 2.071793e+03 7.197675e+01
* time: 0.46520495414733887
9 2.062706e+03 7.623310e+01
* time: 0.5034699440002441
10 2.057515e+03 6.885476e+01
* time: 0.541003942489624
11 2.051133e+03 6.368504e+01
* time: 0.5771958827972412
12 2.038626e+03 7.730243e+01
* time: 0.6136679649353027
13 2.019352e+03 1.136864e+02
* time: 0.6523489952087402
14 1.997136e+03 1.005748e+02
* time: 0.6909389495849609
15 1.983023e+03 6.831478e+01
* time: 0.7352168560028076
16 1.977700e+03 5.649783e+01
* time: 0.7798378467559814
17 1.974583e+03 6.357642e+01
* time: 0.8248069286346436
18 1.967292e+03 7.658974e+01
* time: 0.9084019660949707
19 1.951045e+03 6.130573e+01
* time: 0.959183931350708
20 1.935868e+03 4.845839e+01
* time: 1.025730848312378
21 1.929356e+03 6.325782e+01
* time: 1.0863349437713623
22 1.925187e+03 3.142245e+01
* time: 1.1253979206085205
23 1.923733e+03 4.623400e+01
* time: 1.1632418632507324
24 1.918498e+03 5.347738e+01
* time: 1.2014379501342773
25 1.912383e+03 5.849125e+01
* time: 1.244764804840088
26 1.905510e+03 3.254038e+01
* time: 1.2863948345184326
27 1.903629e+03 2.905618e+01
* time: 1.323462963104248
28 1.902833e+03 2.907696e+01
* time: 1.3623178005218506
29 1.902447e+03 2.746037e+01
* time: 1.3999559879302979
30 1.899399e+03 1.930949e+01
* time: 1.4423038959503174
31 1.898705e+03 1.186361e+01
* time: 1.5081398487091064
32 1.898505e+03 1.050402e+01
* time: 1.5439999103546143
33 1.898474e+03 1.042186e+01
* time: 1.5754528045654297
34 1.897992e+03 1.238729e+01
* time: 1.6078779697418213
35 1.897498e+03 1.729368e+01
* time: 1.6418910026550293
36 1.896954e+03 1.472554e+01
* time: 1.6753458976745605
37 1.896744e+03 5.852825e+00
* time: 1.7081198692321777
38 1.896705e+03 1.171353e+00
* time: 1.737980842590332
39 1.896704e+03 1.216117e+00
* time: 1.7688119411468506
40 1.896703e+03 1.230336e+00
* time: 1.7994458675384521
41 1.896698e+03 1.250715e+00
* time: 1.830901861190796
42 1.896688e+03 1.449552e+00
* time: 1.8623628616333008
43 1.896666e+03 2.533300e+00
* time: 1.8960678577423096
44 1.896631e+03 3.075536e+00
* time: 1.9325978755950928
45 1.896599e+03 2.139797e+00
* time: 1.9917538166046143
46 1.896587e+03 6.636031e-01
* time: 2.0249388217926025
47 1.896585e+03 6.303517e-01
* time: 2.0566539764404297
48 1.896585e+03 5.995265e-01
* time: 2.086967945098877
49 1.896584e+03 5.844159e-01
* time: 2.1187939643859863
50 1.896583e+03 6.083858e-01
* time: 2.151124954223633
51 1.896579e+03 8.145326e-01
* time: 2.1826817989349365
52 1.896570e+03 1.293490e+00
* time: 2.2141737937927246
53 1.896549e+03 1.877705e+00
* time: 2.2457098960876465
54 1.896513e+03 2.217391e+00
* time: 2.277435779571533
55 1.896482e+03 1.658147e+00
* time: 2.3091259002685547
56 1.896466e+03 5.207215e-01
* time: 2.3410727977752686
57 1.896463e+03 1.177468e-01
* time: 2.373464822769165
58 1.896463e+03 1.678937e-02
* time: 2.405090808868408
59 1.896463e+03 2.666635e-03
* time: 2.4585328102111816
60 1.896463e+03 2.666635e-03
* time: 2.5200469493865967
FittedPumasModel
Successful minimization: true
Likelihood approximation: FOCE
Likelihood Optimizer: BFGS
Dynamical system type: Closed form
Log-likelihood value: -1896.4632
Number of subjects: 30
Number of parameters: Fixed Optimized
0 8
Observation records: Active Missing
DV: 540 0
Total: 540 0
---------------------
Estimate
---------------------
tvcl 0.13915
tvvc 3.9754
tvq 0.041988
tvvp 3.5722
Ω₁,₁ 0.23874
Ω₂,₂ 0.081371
σ_add 0.032174
σ_prop 0.061012
---------------------
We can definitely see that, despite not increasing the parameters of the model, our loglikelihood is higher (implying lower objective function value). Furthermore, our additive and combined error values remain almost the same while our Ω
s decreased for CL
and Vc
. This implies that the WT
covariate is definitely assisting in a better model fit by capturing the variability in CL
and Vc
. We’ll compare models in the next step.
Let’s now try to incorporate into this model creatinine clearance (CRCL
) effect on clearance (CL
):
Like the tip above, you can derive covariates or perform any required transformations or scaling as a data wrangling step and pass the derived/transformed into read_pumas
as a covariate. In this particular case, it is easy to create three more columns in the original data as:
@rtransform! pkdata :CRCL_CL = :CRCL / 100
@rtransform! pkdata :ASWT_CL = (:WT / 70)^0.75
@rtransform! pkdata :ASWT_Vc = (:WT / 70)
Then, you bring these covariates into read_pumas
and use them directly on renCL
, CL
and Vc
. This will avoid computations of your transformations during the model fit.
= @model begin
covariate_model_wt_crcl @param begin
∈ RealDomain(; lower = 0)
tvvc ∈ RealDomain(; lower = 0)
tvq ∈ RealDomain(; lower = 0)
tvvp ∈ RealDomain(; lower = 0)
tvcl_hep ∈ RealDomain(; lower = 0)
tvcl_ren ∈ PDiagDomain(2)
Ω ∈ RealDomain(; lower = 0)
σ_add ∈ RealDomain(; lower = 0)
σ_prop ∈ RealDomain()
dCRCL end
@random begin
~ MvNormal(Ω)
η end
@covariates begin
WT
CRCLend
@pre begin
= tvcl_hep * (WT / 70)^0.75
hepCL = tvcl_ren * (CRCL / 100)^dCRCL
renCL = (hepCL + renCL) * exp(η[1])
CL = tvvc * (WT / 70) * exp(η[2])
Vc = tvq
Q = tvvp
Vp end
@dynamics Central1Periph1
@derived begin
:= @. Central / Vc
cp ~ @. Normal(cp, sqrt(cp^2 * σ_prop^2 + σ_add^2))
DV end
end
PumasModel
Parameters: tvvc, tvq, tvvp, tvcl_hep, tvcl_ren, Ω, σ_add, σ_prop, dCRCL
Random effects: η
Covariates: WT, CRCL
Dynamical system variables: Central, Peripheral
Dynamical system type: Closed form
Derived: DV
Observed: DV
In the covariate_model_wt_crcl
model we are keeping our allometric scaling on WT
from before. But we are also adding a new covariate creatinine clearance (CRCL
), dividing clearance (CL
) into hepatic (hepCL
) and renal clearance (renCL
), along with a new parameter dCRCL
.
dCRCL
is the exponent of the power function for the effect of creatinine clearance on renal clearance. In some models this parameter is fixed, however we’ll allow the model to estimate it.
This is a good example on how to add covariate coefficients such as dCRCL
in any Pumas covariate model. Now, let’s fit this model. Note that we need a new initial parameters values’ list since the previous one we used doesn’t include dCRCL
, tvcl_hep
or tvcl_ren
:
= (;
iparams_covariate_model_wt_crcl = 5,
tvvc = 0.01,
tvcl_hep = 0.01,
tvcl_ren = 0.01,
tvq = 10,
tvvp = Diagonal([0.01, 0.01]),
Ω = 0.1,
σ_add = 0.1,
σ_prop = 0.9,
dCRCL )
(tvvc = 5,
tvcl_hep = 0.01,
tvcl_ren = 0.01,
tvq = 0.01,
tvvp = 10,
Ω = [0.01 0.0; 0.0 0.01],
σ_add = 0.1,
σ_prop = 0.1,
dCRCL = 0.9,)
=
fit_covariate_model_wt_crcl fit(covariate_model_wt_crcl, pop, iparams_covariate_model_wt_crcl, FOCE())
[ Info: Checking the initial parameter values.
[ Info: The initial negative log likelihood and its gradient are finite. Check passed.
Iter Function value Gradient norm
0 8.554152e+03 5.650279e+03
* time: 6.699562072753906e-5
1 3.572050e+03 1.302046e+03
* time: 0.2336139678955078
2 3.266947e+03 5.384244e+02
* time: 0.29645705223083496
3 3.150635e+03 1.918079e+02
* time: 0.3518071174621582
4 3.108122e+03 1.277799e+02
* time: 0.40232205390930176
5 3.091358e+03 8.838080e+01
* time: 0.4514639377593994
6 3.082997e+03 8.321689e+01
* time: 0.500093936920166
7 3.076379e+03 8.167702e+01
* time: 0.5494511127471924
8 3.067422e+03 1.177822e+02
* time: 0.6019189357757568
9 3.048580e+03 2.526969e+02
* time: 0.661107063293457
10 2.993096e+03 6.325396e+02
* time: 0.7535440921783447
11 2.965744e+03 7.634718e+02
* time: 1.0046489238739014
12 2.921212e+03 9.704020e+02
* time: 1.1059620380401611
13 2.553649e+03 6.642510e+02
* time: 1.1847500801086426
14 2.319495e+03 3.204711e+02
* time: 1.3167660236358643
15 2.183040e+03 2.174905e+02
* time: 1.421375036239624
16 2.157621e+03 3.150983e+02
* time: 1.4783430099487305
17 2.132395e+03 2.847614e+02
* time: 1.5323691368103027
18 2.084799e+03 1.563370e+02
* time: 1.5849881172180176
19 2.071497e+03 1.006429e+02
* time: 1.6786539554595947
20 2.064983e+03 9.753313e+01
* time: 1.727445125579834
21 2.048289e+03 9.230405e+01
* time: 1.7754809856414795
22 2.020938e+03 1.292359e+02
* time: 1.8222119808197021
23 1.983888e+03 2.284990e+02
* time: 1.8713979721069336
24 1.962132e+03 1.220188e+02
* time: 1.9189250469207764
25 1.945947e+03 1.035894e+02
* time: 1.9631850719451904
26 1.917782e+03 8.246698e+01
* time: 2.0145421028137207
27 1.905967e+03 5.408054e+01
* time: 2.0671679973602295
28 1.898569e+03 2.172222e+01
* time: 2.1201059818267822
29 1.897473e+03 1.689350e+01
* time: 2.171347141265869
30 1.897019e+03 1.666689e+01
* time: 2.2229740619659424
31 1.896796e+03 1.699751e+01
* time: 2.274718999862671
32 1.896559e+03 1.645900e+01
* time: 2.3637280464172363
33 1.896223e+03 1.415504e+01
* time: 2.407750129699707
34 1.895773e+03 1.630081e+01
* time: 2.452207088470459
35 1.895309e+03 1.723930e+01
* time: 2.497921943664551
36 1.895004e+03 1.229983e+01
* time: 2.5436911582946777
37 1.894871e+03 5.385102e+00
* time: 2.588304042816162
38 1.894827e+03 3.465463e+00
* time: 2.6330151557922363
39 1.894816e+03 3.387474e+00
* time: 2.6799120903015137
40 1.894807e+03 3.295388e+00
* time: 2.728188991546631
41 1.894786e+03 3.089194e+00
* time: 2.777161121368408
42 1.894737e+03 2.928080e+00
* time: 2.826712131500244
43 1.894624e+03 3.088723e+00
* time: 2.876559019088745
44 1.894413e+03 3.493791e+00
* time: 2.927276134490967
45 1.894127e+03 3.142865e+00
* time: 3.015350103378296
46 1.893933e+03 2.145253e+00
* time: 3.0607969760894775
47 1.893888e+03 2.172800e+00
* time: 3.1054229736328125
48 1.893880e+03 2.180509e+00
* time: 3.1487860679626465
49 1.893876e+03 2.134257e+00
* time: 3.1914479732513428
50 1.893868e+03 2.032354e+00
* time: 3.2356481552124023
51 1.893846e+03 1.760874e+00
* time: 3.2791149616241455
52 1.893796e+03 1.779016e+00
* time: 3.3269240856170654
53 1.893694e+03 2.018956e+00
* time: 3.3759100437164307
54 1.893559e+03 2.366854e+00
* time: 3.4247360229492188
55 1.893474e+03 3.690142e+00
* time: 3.47455096244812
56 1.893446e+03 3.675109e+00
* time: 3.523712158203125
57 1.893439e+03 3.426419e+00
* time: 3.5726230144500732
58 1.893429e+03 3.183164e+00
* time: 3.6607561111450195
59 1.893398e+03 2.695171e+00
* time: 3.7047131061553955
60 1.893328e+03 2.753548e+00
* time: 3.757009983062744
61 1.893169e+03 3.589748e+00
* time: 3.83332896232605
62 1.892920e+03 3.680718e+00
* time: 3.8928189277648926
63 1.892667e+03 2.568107e+00
* time: 3.93630313873291
64 1.892514e+03 1.087910e+00
* time: 3.9801180362701416
65 1.892493e+03 3.287296e-01
* time: 4.026593923568726
66 1.892492e+03 2.967465e-01
* time: 4.073759078979492
67 1.892492e+03 3.020682e-01
* time: 4.119004964828491
68 1.892491e+03 3.034704e-01
* time: 4.161945104598999
69 1.892491e+03 3.091846e-01
* time: 4.205899953842163
70 1.892491e+03 3.224170e-01
* time: 4.250786066055298
71 1.892490e+03 6.494197e-01
* time: 4.29577898979187
72 1.892488e+03 1.115188e+00
* time: 4.376759052276611
73 1.892483e+03 1.838833e+00
* time: 4.4189629554748535
74 1.892472e+03 2.765371e+00
* time: 4.461066961288452
75 1.892452e+03 3.463807e+00
* time: 4.503055095672607
76 1.892431e+03 2.805270e+00
* time: 4.544783115386963
77 1.892411e+03 5.758916e-01
* time: 4.587821006774902
78 1.892410e+03 1.434041e-01
* time: 4.6302330493927
79 1.892409e+03 1.639246e-01
* time: 4.677207946777344
80 1.892409e+03 1.145856e-01
* time: 4.724751949310303
81 1.892409e+03 3.966861e-02
* time: 4.771382093429565
82 1.892409e+03 3.550808e-02
* time: 4.816441059112549
83 1.892409e+03 3.456241e-02
* time: 4.863898992538452
84 1.892409e+03 3.114018e-02
* time: 4.908630132675171
85 1.892409e+03 4.080806e-02
* time: 5.006025075912476
86 1.892409e+03 6.722726e-02
* time: 5.047101974487305
87 1.892409e+03 1.006791e-01
* time: 5.087952136993408
88 1.892409e+03 1.303988e-01
* time: 5.12930703163147
89 1.892409e+03 1.228919e-01
* time: 5.169641971588135
90 1.892409e+03 6.433813e-02
* time: 5.211593151092529
91 1.892409e+03 1.314164e-02
* time: 5.253737926483154
92 1.892409e+03 4.929931e-04
* time: 5.293926954269409
FittedPumasModel
Successful minimization: true
Likelihood approximation: FOCE
Likelihood Optimizer: BFGS
Dynamical system type: Closed form
Log-likelihood value: -1892.409
Number of subjects: 30
Number of parameters: Fixed Optimized
0 10
Observation records: Active Missing
DV: 540 0
Total: 540 0
-----------------------
Estimate
-----------------------
tvvc 3.9757
tvq 0.042177
tvvp 3.6434
tvcl_hep 0.058572
tvcl_ren 0.1337
Ω₁,₁ 0.18299
Ω₂,₂ 0.081353
σ_add 0.032174
σ_prop 0.06101
dCRCL 1.1331
-----------------------
As before, our loglikelihood is higher (implying lower objective function value). Furthermore, our additive and combined error values remain almost the same while our Ω
on CL
, Ω₁,₁
, decreased. This implies that the CRCL
covariate with an estimated exponent dCRCL
is definitely assisting in a better model fit.
Finally let’s include a separated CL
model based on sex as a third covariate model:
= @model begin
covariate_model_wt_crcl_sex @param begin
∈ RealDomain(; lower = 0)
tvvc ∈ RealDomain(; lower = 0)
tvq ∈ RealDomain(; lower = 0)
tvvp ∈ RealDomain(; lower = 0)
tvcl_hep_M ∈ RealDomain(; lower = 0)
tvcl_hep_F ∈ RealDomain(; lower = 0)
tvcl_ren_M ∈ RealDomain(; lower = 0)
tvcl_ren_F ∈ PDiagDomain(2)
Ω ∈ RealDomain(; lower = 0)
σ_add ∈ RealDomain(; lower = 0)
σ_prop ∈ RealDomain()
dCRCL_M ∈ RealDomain()
dCRCL_F end
@random begin
~ MvNormal(Ω)
η end
@covariates begin
WT
CRCL
SEXend
@pre begin
= ifelse(SEX == "M", tvcl_hep_M, tvcl_hep_F)
tvcl_hep = ifelse(SEX == "M", tvcl_ren_M, tvcl_ren_F)
tvcl_ren = ifelse(SEX == "M", dCRCL_M, dCRCL_F)
dCRCL = tvcl_hep * (WT / 70)^0.75
hepCL = tvcl_ren * (CRCL / 100)^dCRCL
renCL = (hepCL + renCL) * exp(η[1])
CL = tvvc * (WT / 70) * exp(η[2])
Vc = tvq
Q = tvvp
Vp end
@dynamics Central1Periph1
@derived begin
:= @. Central / Vc
cp ~ @. Normal(cp, sqrt(cp^2 * σ_prop^2 + σ_add^2))
DV end
end
PumasModel
Parameters: tvvc, tvq, tvvp, tvcl_hep_M, tvcl_hep_F, tvcl_ren_M, tvcl_ren_F, Ω, σ_add, σ_prop, dCRCL_M, dCRCL_F
Random effects: η
Covariates: WT, CRCL, SEX
Dynamical system variables: Central, Peripheral
Dynamical system type: Closed form
Derived: DV
Observed: DV
In the covariate_model_wt_crcl_sex
model we are keeping our allometric scaling on WT
, the CRCL
effect on renCL
, and the breakdown of CL
into hepCL
and renCL
from before. However we are separating them with different values by sex. Hence, we have a new covariate SEX
and six new parameters in the @param
block by expanding tvcl_hep
, tvcl_ren
, and dCRCL
into male (suffix M
) and female (suffix F
).
This is a good example on how to add create binary values based on covariate values such as SEX
inside the @pre
block with the ifelse
function. Now, let’s fit this model. Note that we need a new initial parameters values’ list since the previous one we used had a single tvcl_hep
, tvcl_ren
, and dCRCL
:
= (;
iparams_covariate_model_wt_crcl_sex = 5,
tvvc = 0.01,
tvcl_hep_M = 0.01,
tvcl_hep_F = 0.01,
tvcl_ren_M = 0.01,
tvcl_ren_F = 0.01,
tvq = 10,
tvvp = Diagonal([0.01, 0.01]),
Ω = 0.1,
σ_add = 0.1,
σ_prop = 0.9,
dCRCL_M = 0.9,
dCRCL_F )
(tvvc = 5,
tvcl_hep_M = 0.01,
tvcl_hep_F = 0.01,
tvcl_ren_M = 0.01,
tvcl_ren_F = 0.01,
tvq = 0.01,
tvvp = 10,
Ω = [0.01 0.0; 0.0 0.01],
σ_add = 0.1,
σ_prop = 0.1,
dCRCL_M = 0.9,
dCRCL_F = 0.9,)
=
fit_covariate_model_wt_crcl_sex fit(covariate_model_wt_crcl_sex, pop, iparams_covariate_model_wt_crcl_sex, FOCE())
[ Info: Checking the initial parameter values.
[ Info: The initial negative log likelihood and its gradient are finite. Check passed.
Iter Function value Gradient norm
0 8.554152e+03 5.650279e+03
* time: 7.295608520507812e-5
1 3.641387e+03 1.432080e+03
* time: 0.09355998039245605
2 3.290450e+03 5.274782e+02
* time: 0.15543007850646973
3 3.185512e+03 2.173676e+02
* time: 0.2118821144104004
4 3.143009e+03 1.479653e+02
* time: 0.2698330879211426
5 3.128511e+03 8.980031e+01
* time: 0.32782912254333496
6 3.123188e+03 5.033125e+01
* time: 0.39075517654418945
7 3.120794e+03 4.279722e+01
* time: 0.45375609397888184
8 3.118627e+03 3.971051e+01
* time: 0.5186901092529297
9 3.115300e+03 8.456587e+01
* time: 0.5837070941925049
10 3.109353e+03 1.350354e+02
* time: 2.1211180686950684
11 3.095894e+03 1.998258e+02
* time: 2.17923903465271
12 2.988214e+03 4.366433e+02
* time: 2.267376184463501
13 2.896081e+03 5.505943e+02
* time: 2.4788661003112793
14 2.652467e+03 7.300323e+02
* time: 3.8669991493225098
15 2.560937e+03 6.973661e+02
* time: 4.256755113601685
16 2.254941e+03 2.740033e+02
* time: 4.370934009552002
17 2.222509e+03 2.034303e+02
* time: 4.498098134994507
18 2.171255e+03 2.449580e+02
* time: 4.602251052856445
19 2.024532e+03 1.121511e+02
* time: 4.7019171714782715
20 1.993723e+03 1.042814e+02
* time: 4.792510986328125
21 1.985113e+03 8.079014e+01
* time: 4.888077974319458
22 1.976757e+03 7.054196e+01
* time: 4.974152088165283
23 1.969970e+03 6.070322e+01
* time: 5.072671175003052
24 1.961095e+03 6.810782e+01
* time: 5.159670114517212
25 1.947983e+03 8.116920e+01
* time: 5.2527430057525635
26 1.930371e+03 8.530051e+01
* time: 5.3479321002960205
27 1.910209e+03 6.993170e+01
* time: 5.442656993865967
28 1.899107e+03 3.362640e+01
* time: 5.543466091156006
29 1.898022e+03 2.642220e+01
* time: 5.611865997314453
30 1.897055e+03 1.213144e+01
* time: 5.680430173873901
31 1.896596e+03 7.773239e+00
* time: 5.749536037445068
32 1.896538e+03 7.997039e+00
* time: 5.815093994140625
33 1.896451e+03 8.160909e+00
* time: 5.879706144332886
34 1.896283e+03 8.237721e+00
* time: 5.966552019119263
35 1.895903e+03 1.520219e+01
* time: 6.053897142410278
36 1.895272e+03 2.358916e+01
* time: 6.12993597984314
37 1.894536e+03 2.461296e+01
* time: 6.218669176101685
38 1.893995e+03 1.546128e+01
* time: 6.306293964385986
39 1.893858e+03 6.976137e+00
* time: 6.398015022277832
40 1.893833e+03 6.019466e+00
* time: 6.471220016479492
41 1.893786e+03 3.827201e+00
* time: 6.542675971984863
42 1.893714e+03 3.323412e+00
* time: 6.610147953033447
43 1.893592e+03 3.215150e+00
* time: 6.656937122344971
44 1.893435e+03 6.534965e+00
* time: 6.703886032104492
45 1.893286e+03 7.424154e+00
* time: 6.766718149185181
46 1.893190e+03 5.552627e+00
* time: 6.814779043197632
47 1.893139e+03 3.222316e+00
* time: 6.861797094345093
48 1.893120e+03 3.015339e+00
* time: 6.907350063323975
49 1.893107e+03 3.244809e+00
* time: 6.951519966125488
50 1.893080e+03 6.163100e+00
* time: 6.997014045715332
51 1.893027e+03 9.824713e+00
* time: 7.058634042739868
52 1.892912e+03 1.390100e+01
* time: 7.10608696937561
53 1.892734e+03 1.510937e+01
* time: 7.153138160705566
54 1.892561e+03 1.008563e+01
* time: 7.199366092681885
55 1.892485e+03 3.730668e+00
* time: 7.245110034942627
56 1.892471e+03 3.380261e+00
* time: 7.2892069816589355
57 1.892463e+03 3.167904e+00
* time: 7.349027156829834
58 1.892441e+03 4.152065e+00
* time: 7.394813060760498
59 1.892391e+03 7.355996e+00
* time: 7.4400999546051025
60 1.892268e+03 1.195397e+01
* time: 7.486729145050049
61 1.892026e+03 1.640783e+01
* time: 7.532876968383789
62 1.891735e+03 1.593576e+01
* time: 7.595043182373047
63 1.891569e+03 8.316423e+00
* time: 7.643293142318726
64 1.891494e+03 3.948212e+00
* time: 7.6889731884002686
65 1.891481e+03 3.911593e+00
* time: 7.733180999755859
66 1.891457e+03 3.875559e+00
* time: 7.777536153793335
67 1.891405e+03 3.811247e+00
* time: 7.822023153305054
68 1.891262e+03 3.657045e+00
* time: 7.88151216506958
69 1.890930e+03 4.957405e+00
* time: 7.928992033004761
70 1.890317e+03 6.657726e+00
* time: 7.978309154510498
71 1.889660e+03 6.086302e+00
* time: 8.026012182235718
72 1.889303e+03 2.270929e+00
* time: 8.07204008102417
73 1.889253e+03 7.695301e-01
* time: 8.117138147354126
74 1.889252e+03 7.382144e-01
* time: 8.176329135894775
75 1.889251e+03 7.187898e-01
* time: 8.22130799293518
76 1.889251e+03 7.215047e-01
* time: 8.264449119567871
77 1.889250e+03 7.235155e-01
* time: 8.307260990142822
78 1.889249e+03 7.246818e-01
* time: 8.350273132324219
79 1.889244e+03 7.257796e-01
* time: 8.394158124923706
80 1.889233e+03 7.198190e-01
* time: 8.454494953155518
81 1.889204e+03 1.089029e+00
* time: 8.502465963363647
82 1.889142e+03 1.801601e+00
* time: 8.549183130264282
83 1.889043e+03 2.967917e+00
* time: 8.59532904624939
84 1.888889e+03 2.965856e+00
* time: 8.645277976989746
85 1.888705e+03 5.933557e-01
* time: 8.69391417503357
86 1.888655e+03 9.577696e-01
* time: 8.775105953216553
87 1.888582e+03 1.498494e+00
* time: 8.821997165679932
88 1.888533e+03 1.502753e+00
* time: 8.868581056594849
89 1.888490e+03 1.184664e+00
* time: 8.916514158248901
90 1.888480e+03 6.684517e-01
* time: 8.963972091674805
91 1.888476e+03 3.680034e-01
* time: 9.02361512184143
92 1.888476e+03 4.720040e-01
* time: 9.084444999694824
93 1.888476e+03 4.768646e-01
* time: 9.138576984405518
94 1.888475e+03 4.736673e-01
* time: 9.18110203742981
95 1.888475e+03 4.552764e-01
* time: 9.223320007324219
96 1.888474e+03 5.193733e-01
* time: 9.265405178070068
97 1.888473e+03 8.850112e-01
* time: 9.3227219581604
98 1.888468e+03 1.461600e+00
* time: 9.367063999176025
99 1.888458e+03 2.209127e+00
* time: 9.41123104095459
100 1.888437e+03 2.961239e+00
* time: 9.455619096755981
101 1.888407e+03 2.978463e+00
* time: 9.501255989074707
102 1.888384e+03 1.707201e+00
* time: 9.545618057250977
103 1.888381e+03 6.199354e-01
* time: 9.605647087097168
104 1.888380e+03 5.170909e-01
* time: 9.651757001876831
105 1.888378e+03 1.037408e-01
* time: 9.69723105430603
106 1.888378e+03 8.473247e-02
* time: 9.738769054412842
107 1.888378e+03 8.364978e-02
* time: 9.78000807762146
108 1.888378e+03 8.080446e-02
* time: 9.821596145629883
109 1.888378e+03 7.873905e-02
* time: 9.87653398513794
110 1.888378e+03 7.798398e-02
* time: 9.91849398612976
111 1.888378e+03 7.788170e-02
* time: 9.9601731300354
112 1.888378e+03 7.776461e-02
* time: 10.000357151031494
113 1.888378e+03 9.023662e-02
* time: 10.040759086608887
114 1.888378e+03 1.631390e-01
* time: 10.081798076629639
115 1.888378e+03 2.768731e-01
* time: 10.138453960418701
116 1.888377e+03 4.462386e-01
* time: 10.182181119918823
117 1.888377e+03 6.643297e-01
* time: 10.226317167282104
118 1.888375e+03 8.433397e-01
* time: 10.269840955734253
119 1.888374e+03 7.596814e-01
* time: 10.31320309638977
120 1.888373e+03 3.638119e-01
* time: 10.356076002120972
121 1.888372e+03 8.306034e-02
* time: 10.41214895248413
122 1.888372e+03 2.084513e-02
* time: 10.455090999603271
123 1.888372e+03 2.056419e-02
* time: 10.498250961303711
124 1.888372e+03 2.044080e-02
* time: 10.537997961044312
125 1.888372e+03 2.035196e-02
* time: 10.5762460231781
126 1.888372e+03 2.021264e-02
* time: 10.614962100982666
127 1.888372e+03 1.998163e-02
* time: 10.65455412864685
128 1.888372e+03 3.161638e-02
* time: 10.710819005966187
129 1.888372e+03 5.509218e-02
* time: 10.75266408920288
130 1.888372e+03 9.275848e-02
* time: 10.793850183486938
131 1.888372e+03 1.528749e-01
* time: 10.834737062454224
132 1.888372e+03 2.461766e-01
* time: 10.876012086868286
133 1.888372e+03 3.799362e-01
* time: 10.917564153671265
134 1.888371e+03 5.311665e-01
* time: 10.976363182067871
135 1.888369e+03 6.019039e-01
* time: 11.020753145217896
136 1.888367e+03 4.664896e-01
* time: 11.064316034317017
137 1.888366e+03 1.404934e-01
* time: 11.10679006576538
138 1.888365e+03 8.513331e-02
* time: 11.149557113647461
139 1.888364e+03 1.244077e-01
* time: 11.191015005111694
140 1.888364e+03 1.028085e-01
* time: 11.248507022857666
141 1.888364e+03 5.162231e-02
* time: 11.292840957641602
142 1.888364e+03 5.149630e-02
* time: 11.335594177246094
143 1.888364e+03 3.147284e-02
* time: 11.377110958099365
144 1.888364e+03 2.104766e-02
* time: 11.417720079421997
145 1.888364e+03 6.539151e-03
* time: 11.45687198638916
146 1.888364e+03 2.540196e-03
* time: 11.51254916191101
147 1.888364e+03 4.362661e-03
* time: 11.553251028060913
148 1.888364e+03 3.034416e-03
* time: 11.59301209449768
149 1.888364e+03 5.953892e-04
* time: 11.631872177124023
FittedPumasModel
Successful minimization: true
Likelihood approximation: FOCE
Likelihood Optimizer: BFGS
Dynamical system type: Closed form
Log-likelihood value: -1888.3638
Number of subjects: 30
Number of parameters: Fixed Optimized
0 13
Observation records: Active Missing
DV: 540 0
Total: 540 0
--------------------------
Estimate
--------------------------
tvvc 3.976
tvq 0.04239
tvvp 3.7249
tvcl_hep_M 1.7175e-7
tvcl_hep_F 0.13348
tvcl_ren_M 0.19378
tvcl_ren_F 0.042211
Ω₁,₁ 0.14046
Ω₂,₂ 0.081349
σ_add 0.032171
σ_prop 0.061007
dCRCL_M 0.94821
dCRCL_F 1.9405
--------------------------
As before, our loglikelihood is higher (implying lower objective function value). This is expected since we also added six new parameters to the model.
5 Step 4 - Model Comparison
Now that we’ve fitted all of our models we need to compare them and choose one for our final model.
We begin by analyzing the model metrics. This can be done with the metrics_table
function:
metrics_table(fit_base_model)
WARNING: using deprecated binding Distributions.MatrixReshaped in Pumas.
, use Distributions.ReshapedDistribution{2, S, D} where D<:Distributions.Distribution{Distributions.ArrayLikeVariate{1}, S} where S<:Distributions.ValueSupport instead.
Row | Metric | Value |
---|---|---|
String | Any | |
1 | Successful | true |
2 | Estimation Time | 3.794 |
3 | Subjects | 30 |
4 | Fixed Parameters | 0 |
5 | Optimized Parameters | 8 |
6 | DV Active Observations | 540 |
7 | DV Missing Observations | 0 |
8 | Total Active Observations | 540 |
9 | Total Missing Observations | 0 |
10 | Likelihood Approximation | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} |
11 | LogLikelihood (LL) | -1901.82 |
12 | -2LL | 3803.63 |
13 | AIC | 3819.63 |
14 | BIC | 3853.96 |
15 | (η-shrinkage) η₁ | -0.015 |
16 | (η-shrinkage) η₂ | -0.013 |
17 | (ϵ-shrinkage) DV | 0.056 |
metrics_table(fit_covariate_model_wt)
Row | Metric | Value |
---|---|---|
String | Any | |
1 | Successful | true |
2 | Estimation Time | 2.52 |
3 | Subjects | 30 |
4 | Fixed Parameters | 0 |
5 | Optimized Parameters | 8 |
6 | DV Active Observations | 540 |
7 | DV Missing Observations | 0 |
8 | Total Active Observations | 540 |
9 | Total Missing Observations | 0 |
10 | Likelihood Approximation | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} |
11 | LogLikelihood (LL) | -1896.46 |
12 | -2LL | 3792.93 |
13 | AIC | 3808.93 |
14 | BIC | 3843.26 |
15 | (η-shrinkage) η₁ | -0.014 |
16 | (η-shrinkage) η₂ | -0.012 |
17 | (ϵ-shrinkage) DV | 0.056 |
metrics_table(fit_covariate_model_wt_crcl)
Row | Metric | Value |
---|---|---|
String | Any | |
1 | Successful | true |
2 | Estimation Time | 5.294 |
3 | Subjects | 30 |
4 | Fixed Parameters | 0 |
5 | Optimized Parameters | 10 |
6 | DV Active Observations | 540 |
7 | DV Missing Observations | 0 |
8 | Total Active Observations | 540 |
9 | Total Missing Observations | 0 |
10 | Likelihood Approximation | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} |
11 | LogLikelihood (LL) | -1892.41 |
12 | -2LL | 3784.82 |
13 | AIC | 3804.82 |
14 | BIC | 3847.73 |
15 | (η-shrinkage) η₁ | -0.014 |
16 | (η-shrinkage) η₂ | -0.012 |
17 | (ϵ-shrinkage) DV | 0.056 |
metrics_table(fit_covariate_model_wt_crcl_sex)
Row | Metric | Value |
---|---|---|
String | Any | |
1 | Successful | true |
2 | Estimation Time | 11.632 |
3 | Subjects | 30 |
4 | Fixed Parameters | 0 |
5 | Optimized Parameters | 13 |
6 | DV Active Observations | 540 |
7 | DV Missing Observations | 0 |
8 | Total Active Observations | 540 |
9 | Total Missing Observations | 0 |
10 | Likelihood Approximation | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} |
11 | LogLikelihood (LL) | -1888.36 |
12 | -2LL | 3776.73 |
13 | AIC | 3802.73 |
14 | BIC | 3858.52 |
15 | (η-shrinkage) η₁ | -0.013 |
16 | (η-shrinkage) η₂ | -0.012 |
17 | (ϵ-shrinkage) DV | 0.056 |
metrics_table
outputs all of the model metrics we might be interested with respect to a certain model. That includes metadata such as estimation time, number of subjects, how many parameters were optimized and fixed, and number of observations. It also includes common model metrics like AIC, BIC, objective function value with constant (-2 loglikelihood), and so on.
We can also do an innerjoin
(check our Data Wrangling Tutorials) to get all metrics into a single DataFrame
:
= innerjoin(
all_metrics metrics_table(fit_base_model),
metrics_table(fit_covariate_model_wt),
metrics_table(fit_covariate_model_wt_crcl),
metrics_table(fit_covariate_model_wt_crcl_sex);
= :Metric,
on = true,
makeunique
);rename!(
all_metrics,:Value => :Base_Model,
:Value_1 => :Covariate_Model_WT,
:Value_2 => :Covariate_Model_WT_CRCL,
:Value_3 => :Covariate_Model_WT_CRCL_SEX,
)
Row | Metric | Base_Model | Covariate_Model_WT | Covariate_Model_WT_CRCL | Covariate_Model_WT_CRCL_SEX |
---|---|---|---|---|---|
String | Any | Any | Any | Any | |
1 | Successful | true | true | true | true |
2 | Estimation Time | 3.794 | 2.52 | 5.294 | 11.632 |
3 | Subjects | 30 | 30 | 30 | 30 |
4 | Fixed Parameters | 0 | 0 | 0 | 0 |
5 | Optimized Parameters | 8 | 8 | 10 | 13 |
6 | DV Active Observations | 540 | 540 | 540 | 540 |
7 | DV Missing Observations | 0 | 0 | 0 | 0 |
8 | Total Active Observations | 540 | 540 | 540 | 540 |
9 | Total Missing Observations | 0 | 0 | 0 | 0 |
10 | Likelihood Approximation | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} | Pumas.FOCE{Optim.NewtonTrustRegion{Float64}, Optim.Options{Float64, Nothing}} |
11 | LogLikelihood (LL) | -1901.82 | -1896.46 | -1892.41 | -1888.36 |
12 | -2LL | 3803.63 | 3792.93 | 3784.82 | 3776.73 |
13 | AIC | 3819.63 | 3808.93 | 3804.82 | 3802.73 |
14 | BIC | 3853.96 | 3843.26 | 3847.73 | 3858.52 |
15 | (η-shrinkage) η₁ | -0.015 | -0.014 | -0.014 | -0.013 |
16 | (η-shrinkage) η₂ | -0.013 | -0.012 | -0.012 | -0.012 |
17 | (ϵ-shrinkage) DV | 0.056 | 0.056 | 0.056 | 0.056 |
We can also use specific functions to retrieve those. For example, in order to get a model’s AIC you can use the aic
function:
aic(fit_base_model)
3819.629984952819
aic(fit_covariate_model_wt)
3808.9264607805967
aic(fit_covariate_model_wt_crcl)
3804.817947371705
aic(fit_covariate_model_wt_crcl_sex)
3802.7275243741956
We should favor lower values of AIC, hence, the covariate model with weight, creatinine clerance, and different sex effects on clearance should be preferred, i.e. covariate_model_wt_crcl_sex
.
5.1 Goodness of Fit Plots
Additionally, we should inspect the goodness of fit of the model. This is done with the plotting function goodness_of_fit
, which should be given a result from a inspect
function. So, let’s first call inspect
on our covariate_model_wt_crcl_sex
candidate for best model:
= inspect(fit_covariate_model_wt_crcl_sex) inspect_covariate_model_wt_crcl_sex
[ Info: Calculating predictions.
[ Info: Calculating weighted residuals.
[ Info: Calculating empirical bayes.
[ Info: Evaluating individual parameters.
[ Info: Evaluating dose control parameters.
[ Info: Done.
FittedPumasModelInspection
Fitting was successful: true
Likehood approximation used for weighted residuals: FOCE
And now we pass inspect_covariate_model_wt_crcl_sex
to the goodness_of_fit
plotting function:
goodness_of_fit(inspect_covariate_model_wt_crcl_sex)
The idea is that the population predictions (preds) capture the general tendency of the observations while the individual predictions (ipreds) should coincide much more closely with the observations. That is exactly what we are observing in the top row subplots in our goodness of fit plot.
Regarding the bottom row, on the left we have the weighted population residuals (wres) against time, and on the right we have the weighted individual residuals (iwres) against ipreds. Here we should not see any perceived pattern, which indicates that the error model in the model has a mean 0 and constant variance. Like before, this seems to be what we are observing in our goodness of fit plot.
Hence, our covariate model with allometric scaling and different sex creatinine clearance effectw on clearance is a good candidate for our final model.
6 Time-Varying Covariates
Pumas can handle time-varying covariates. This happens automatically if, when parsing a dataset, read_pumas
detects that covariate values change over time.
6.1 painord
Dataset
Here’s an example with an ordinal regression using the painord
dataset from PharmaDatasets.jl
. :painord
is our observations measuring the perceived pain in a scale from 0 to 3, which we need to have the range shifted by 1 (1 to 4). Additionally, we’ll use the concentration in plasma, :conc
as a covariate. Of course, :conc
varies with time, thus, it is a time-varying covariate:
= dataset("pumas/pain_remed")
painord first(painord, 5)
Row | id | arm | dose | time | conc | painord | dv | remed |
---|---|---|---|---|---|---|---|---|
Int64 | Int64 | Int64 | Float64 | Float64 | Int64 | Int64 | Int64 | |
1 | 1 | 2 | 20 | 0.0 | 0.0 | 3 | 0 | 0 |
2 | 1 | 2 | 20 | 0.5 | 1.15578 | 1 | 1 | 0 |
3 | 1 | 2 | 20 | 1.0 | 1.37211 | 0 | 1 | 0 |
4 | 1 | 2 | 20 | 1.5 | 1.30058 | 0 | 1 | 0 |
5 | 1 | 2 | 20 | 2.0 | 1.19195 | 1 | 1 | 0 |
@rtransform! painord :painord = :painord + 1;
describe(painord, :mean, :std, :first, :last, :eltype)
Row | variable | mean | std | first | last | eltype |
---|---|---|---|---|---|---|
Symbol | Float64 | Float64 | Real | Real | DataType | |
1 | id | 80.5 | 46.1992 | 1 | 160 | Int64 |
2 | arm | 1.5 | 1.11833 | 2 | 0 | Int64 |
3 | dose | 26.25 | 31.9017 | 20 | 0 | Int64 |
4 | time | 3.375 | 2.5183 | 0.0 | 8.0 | Float64 |
5 | conc | 0.93018 | 1.49902 | 0.0 | 0.0 | Float64 |
6 | painord | 2.50208 | 0.863839 | 4 | 4 | Int64 |
7 | dv | 0.508333 | 0.500061 | 0 | 0 | Int64 |
8 | remed | 0.059375 | 0.236387 | 0 | 0 | Int64 |
unique(painord.dose)
4-element Vector{Int64}:
20
80
0
5
As we can see we have 160 subjects were given either 0, 5, 20, or 80 units of a certain painkiller drug.
:conc
is the drug concentration in plasma and :painord
is the perceived pain in a scale from 1 to 4.
First, we’ll parse the painord
dataset into a Population
. Note that we’ll be using event_data=false
since we do not have any dosing rows:
=
pop_ord read_pumas(painord; observations = [:painord], covariates = [:conc], event_data = false)
We won’t be going into the details of the ordinal regression model in this tutorial. We highly encourage you to take a look at the Ordinal Regression Pumas Tutorial for an in-depth explanation.
We’ll build an ordinal regression model declaring :conc
as a covariate. In the @derived
block we’ll state the the likelihood of :painord
follows a Categorical
distribution:
= @model begin
ordinal_model @param begin
∈ RealDomain(; init = 0)
b₁ ∈ RealDomain(; init = 1)
b₂ ∈ RealDomain(; init = 1)
b₃ ∈ RealDomain(; init = 0)
slope end
@covariates conc # time-varying
@pre begin
= slope * conc
effect
# Logit of cumulative probabilities
= b₁ + effect
lge₁ = lge₁ - b₂
lge₂ = lge₂ - b₃
lge₃
# Probabilities of >=1 and >=2 and >=3
= logistic(lge₁)
pge₁ = logistic(lge₂)
pge₂ = logistic(lge₃)
pge₃
# Probabilities of Y=1,2,3,4
= 1.0 - pge₁
p₁ = pge₁ - pge₂
p₂ = pge₂ - pge₃
p₃ = pge₃
p₄ end
@derived begin
~ @. Categorical(p₁, p₂, p₃, p₄)
painord end
end
PumasModel
Parameters: b₁, b₂, b₃, slope
Random effects:
Covariates: conc
Dynamical system variables:
Dynamical system type: No dynamical model
Derived: painord
Observed: painord
Finally we’ll fit our model using NaivePooled
estimation method since it does not have any random-effects, i.e. no @random
block:
= fit(ordinal_model, pop_ord, init_params(ordinal_model), NaivePooled()) ordinal_fit
[ Info: Checking the initial parameter values.
[ Info: The initial negative log likelihood and its gradient are finite. Check passed.
Iter Function value Gradient norm
0 3.103008e+03 7.031210e+02
* time: 6.818771362304688e-5
1 2.994747e+03 1.083462e+03
* time: 0.005970001220703125
2 2.406265e+03 1.884408e+02
* time: 0.011843204498291016
3 2.344175e+03 7.741610e+01
* time: 0.01760101318359375
4 2.323153e+03 2.907642e+01
* time: 0.023398160934448242
5 2.318222e+03 2.273295e+01
* time: 0.029120206832885742
6 2.316833e+03 1.390527e+01
* time: 0.03482699394226074
7 2.316425e+03 4.490883e+00
* time: 0.04061007499694824
8 2.316362e+03 9.374519e-01
* time: 0.046227216720581055
9 2.316356e+03 1.928785e-01
* time: 0.05182600021362305
10 2.316355e+03 3.119615e-02
* time: 0.05752921104431152
11 2.316355e+03 6.215513e-03
* time: 0.06323504447937012
12 2.316355e+03 8.313206e-04
* time: 0.06901812553405762
FittedPumasModel
Successful minimization: true
Likelihood approximation: NaivePooled
Likelihood Optimizer: BFGS
Dynamical system type: No dynamical model
Log-likelihood value: -2316.3554
Number of subjects: 160
Number of parameters: Fixed Optimized
0 4
Observation records: Active Missing
painord: 1920 0
Total: 1920 0
-------------------
Estimate
-------------------
b₁ 2.5112
b₂ 2.1951
b₃ 1.9643
slope -0.38871
-------------------
As expected, the ordinal model fit estimates a negative effect of :conc
on :painord
measured by the slope
parameter.
7 Missing Data in Covariates
The way how Pumas handles missing values inside covariates depends if the covariate is constant or time-varying. For both cases Pumas will interpolate the available values to fill in the missing values. If, for any subject, all of the covariate’s values are missing, Pumas will throw an error while parsing the data with read_pumas
.
For both missing constant and time-varying covariates, Pumas, by default, does piece-wise constant interpolation with “next observation carried backward” (NOCB, NONMEM default). Of course for constant covariates the interpolated values over the missing values will be constant values. This can be adjusted with the covariates_direction
keyword argument of read_pumas
. The default value :right
is NOCB and :left
is “last observation carried forward” (LOCF, Monolix default).
Hence, for LOCF, you can use the following:
= read_pumas(pkdata; covariates_direction = :left) pop
along with any other required keyword arguments for column mapping.
The same behavior for covariates_direction
applies to time-varying covariates during the interpolation in the ODE solver. They will also be piece-wise constant interpolated following either NOCB or LOCF depending on the covariates_direction
value.
8 Categorical Covariates
In some situations, you’ll find yourself with categorical covariates with multiple levels, instead of binary or continuous covariates. Categorical covariates are covariates that can take on a finite number of distinct values.
Pumas can easily address categorical covariates. In the @pre
block you can use a nested if ... elseif ... else
statement to handle the different categories.
For example:
@pre begin
= if RACE == 1
CL * (WT / 70)^dwtdcl * exp(η[1]) * drace1dcl
tvcl elseif RACE == 2
* (WT / 70)^dwtdcl * exp(η[1]) * drace2dcl
tvcl elseif RACE == 3
* (WT / 70)^dwtdcl * exp(η[1]) * drace3dcl
tvcl end
end
Here we are conditioning the clearance (CL
) on the RACE
covariate by modulating which population-level parameter will be used for the clearance calculation: drace1dcl
, drace2dcl
, and drace3dcl
.
There’s nothing wrong with the code above, but it can be a bit cumbersome to write and read. In order to make it more readable and maintainable, you can use the following example:
@pre begin
= race1cl^(race == 1) * race2cl^(race == 2) * race3cl^(race == 3)
raceoncl = tvcl * raceoncl
CL end
Here we are using the ^
operator to raise each race
value to the power of the race1cl
, race2cl
, and race3cl
values. If any of the race
values is not equal to the race
value, the result will be 1
, otherwise it will be the respective race1cl
, race2cl
, or race3cl
value.
9 Conclusion
This tutorial shows how to build covariate model in Pumas in a workflow approach. The main purpose was to inform how to:
- parse covariate data into a
Population
- add covariate information into a model
We also went over what are the differences between constant and time-varying covariates and how does Pumas deal with missing data inside covariates.