Skip to content

Non-compartmental analysis on CAMPSIS simulation output

License

Notifications You must be signed in to change notification settings

Calvagone/campsisnca

Repository files navigation

campsisnca

R-CMD-check Codecov test coverage

Analyse your simulation output using non-compartmental analysis.

Installation

Install the latest stable release as follows:

devtools::install_github("Calvagone/campsisnca")

Basic use

First import the campsisnca and gtsummary packages as follows:

library(campsisnca)
library(gtsummary)
library(gt)

Example 1: PK metrics at Day 1 and Day 7

Assume some results were simulated with Campsis (see campsis dataframe) :

campsis <- generateTestData()
campsis
## # A tibble: 5,000 × 16
##       ID  TIME   ARM   A_DEPOT A_CENTRAL A_PERIPHERAL A_OUTPUT    BW    CL    V2
##    <dbl> <dbl> <dbl>     <dbl>     <dbl>        <dbl>    <dbl> <dbl> <dbl> <dbl>
##  1     1     0     0   0              0           0        0    93.6  5.89  94.8
##  2     1     1     0   4.31e+2      538.         11.3     19.4  93.6  5.89  94.8
##  3     1     2     0   1.86e+2      722.         32.4     59.7  93.6  5.89  94.8
##  4     1     4     0   3.44e+1      741.         71.7    153.   93.6  5.89  94.8
##  5     1     6     0   6.39e+0      657.         96.3    240.   93.6  5.89  94.8
##  6     1     8     0   1.19e+0      574.        108.     316.   93.6  5.89  94.8
##  7     1    12     0   4.09e-2      447.        110.     442.   93.6  5.89  94.8
##  8     1    16     0   1.41e-3      358.         99.8    542.   93.6  5.89  94.8
##  9     1    24     0   1.67e-6      239.         72.7    688.   93.6  5.89  94.8
## 10     1    48     0   1.67e-6      316.         96.4   1588.   93.6  5.89  94.8
## # ℹ 4,990 more rows
## # ℹ 6 more variables: Q <dbl>, V3 <dbl>, KA <dbl>, CP <dbl>, OBS_CP <dbl>,
## #   Y <dbl>

Let’s calculate PK metrics at Day 1 and Day 7 as follows:

# Day 1
ncaD1 <- NCAMetrics(x=campsis %>% timerange(0, 24), variable="Y", scenario=c(day="Day 1")) %>%
  add(c(AUC(unit="ng/mL*h"), Cmax(unit="ng/mL"), Tmax(unit="h"), Ctrough(unit="ng/mL"))) %>%
  calculate()

# Day 7 
ncaD7 <- NCAMetrics(x=campsis %>% timerange(144, 168, rebase=TRUE), variable="Y", scenario=c(day="Day 7")) %>%
  add(c(AUC(), Cmax(), Tmax(), Ctrough())) %>%
  calculate()

These 2 metrics may be imported into a metrics table object, as follows:

table <- NCAMetricsTable() %>%
  add(c(ncaD1, ncaD7))

This table can be exported:

  1. To a dataframe using the export function:
table %>% export(dest="dataframe")
## # A tibble: 24 × 4
##    metric  stat    value day  
##    <chr>   <chr>   <dbl> <chr>
##  1 AUC     median 134.   Day 1
##  2 AUC     p5     102.   Day 1
##  3 AUC     p95    168.   Day 1
##  4 Cmax    median  10.2  Day 1
##  5 Cmax    p5       7.85 Day 1
##  6 Cmax    p95     13.1  Day 1
##  7 tmax    median   2    Day 1
##  8 tmax    p5       1    Day 1
##  9 tmax    p95      6    Day 1
## 10 Ctrough median   2.89 Day 1
## # ℹ 14 more rows

When type is not specified, default value is summary. Argument type can also be summary_wide or summary_pretty. In the latter case, summary statistics are exported according to the arguments stat_display and digits provided for each metric.

  1. To an HTML table using gt:
table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric Day 1
N = 200
1
Day 7
N = 200
1
AUC (ng/mL*h) 134 (102–168) 199 (131–297)
Cmax (ng/mL) 10.2 (7.8–13.1) 14.8 (10.4–20.6)
tmax (h) 2.00 (1.00–6.00) 2.00 (1.00–6.00)
Ctrough (ng/mL) 2.89 (1.43–4.50) 4.18 (1.99–8.75)
1 Median (5% Centile–95% Centile)

Please note the individual metrics can also be exported to a dataframe using the export function as follows:

table %>% export(dest="dataframe", type="individual_wide")
## # A tibble: 400 × 6
##       id day     AUC  Cmax  tmax Ctrough
##    <dbl> <chr> <dbl> <dbl> <dbl>   <dbl>
##  1     1 Day 1 122.   9.78     4    2.75
##  2     2 Day 1  92.6  6.11     6    1.70
##  3     3 Day 1 119.  10.9      2    1.97
##  4     4 Day 1 131.   9.72     2    1.99
##  5     5 Day 1 166.  10.1      4    3.79
##  6     6 Day 1 152.  10.1      2    3.04
##  7     7 Day 1 134.   9.28     2    2.70
##  8     8 Day 1 163.  13.7      2    2.91
##  9     9 Day 1 111.   9.62     2    1.94
## 10    10 Day 1 118.   9.91     4    2.90
## # ℹ 390 more rows

Example 2: PK metrics at Day 1 and Day 7 for different body weight ranges

library(dplyr)
campsis_bw_50_75 <- campsis %>% filter(BW > 50 & BW < 75)
campsis_bw_75_100 <- campsis %>% filter(BW >= 75 & BW < 100)

scenarioD1_a <- c(day="Day 1", bw_range="BW range: 50-75")
ncaD1_a <- NCAMetrics(x=campsis_bw_50_75 %>% timerange(0, 24), variable="Y", scenario=scenarioD1_a) %>% 
  add(c(AUC(unit="ng/mL*h"), Cmax(unit="ng/mL"), Tmax(unit="h"), Ctrough(unit="ng/mL"))) %>%
  calculate()

scenarioD7_a <- c(day="Day 7", bw_range="BW range: 50-75")
ncaD7_a <- NCAMetrics(x=campsis_bw_50_75 %>% timerange(144, 168, rebase=T), variable="Y", scenario=scenarioD7_a) %>%
  add(c(AUC(), Cmax(), Tmax(), Ctrough())) %>%
  calculate()

scenarioD1_b <- c(day="Day 1", bw_range="BW range: 75-100")
ncaD1_b <- NCAMetrics(x=campsis_bw_75_100 %>% timerange(0, 24), variable="Y", scenario=scenarioD1_b) %>%
  add(c(AUC(), Cmax(), Tmax(), Ctrough())) %>%
  calculate()

scenarioD7_b <- c(day="Day 7", bw_range="BW range: 75-100")
ncaD7_b <- NCAMetrics(x=campsis_bw_75_100 %>% timerange(144, 168, rebase=T), variable="Y", scenario=scenarioD7_b) %>%
  add(c(AUC(), Cmax(), Tmax(), Ctrough())) %>%
  calculate()

table <- NCAMetricsTable() %>%
  add(c(ncaD1_a, ncaD7_a, ncaD1_b, ncaD7_b))
table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric BW range: 50-75
N = 103
1
BW range: 75-100
N = 97
1
Day 1
AUC (ng/mL*h) 144 (120–174) 122 (98–154)
Cmax (ng/mL) 10.26 (8.23–13.42) 10.17 (7.47–12.80)
tmax (h) 2.00 (1.00–6.00) 2.00 (1.00–6.00)
Ctrough (ng/mL) 3.46 (2.20–4.60) 2.24 (1.25–3.90)
Day 7
AUC (ng/mL*h) 233 (164–305) 168 (121–236)
Cmax (ng/mL) 16.4 (12.6–21.1) 13.4 (9.9–18.4)
tmax (h) 2.00 (1.00–6.00) 2.00 (1.00–6.00)
Ctrough (ng/mL) 5.95 (3.03–9.21) 3.23 (1.27–5.85)
1 Median (5% Centile–95% Centile)
# Alternatively, first stratification variable can be seen in columns (use of 'tbl_merge' within gtsummary)
table %>% export(dest="gt", subscripts=TRUE, combine_with="tbl_merge") %>% as_raw_html()
Metric
Day 1
Day 7
BW range: 50-75
N = 103
1
BW range: 75-100
N = 97
1
BW range: 50-75
N = 103
1
BW range: 75-100
N = 97
1
AUC (ng/mL*h) 144 (120–174) 122 (98–154) 233 (164–305) 168 (121–236)
Cmax (ng/mL) 10.26 (8.23–13.42) 10.17 (7.47–12.80) 16.4 (12.6–21.1) 13.4 (9.9–18.4)
tmax (h) 2.00 (1.00–6.00) 2.00 (1.00–6.00) 2.00 (1.00–6.00) 2.00 (1.00–6.00)
Ctrough (ng/mL) 3.46 (2.20–4.60) 2.24 (1.25–3.90) 5.95 (3.03–9.21) 3.23 (1.27–5.85)
1 Median (5% Centile–95% Centile)

Example 3: Calculate 2-compartment half-life metrics

nca <- NCAMetrics(x=campsis %>% mutate(DOSE=1000, TAU=24), variable="Y") %>%
  add(c(Thalf.2cpt.dist(), Thalf.2cpt.eff(), Thalf.2cpt.z())) %>%
  calculate()

table <- NCAMetricsTable() %>%
  add(nca)
table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric N = 2001
t½,dist 2.57 (1.91–3.51)
t½,eff 13.4 (8.3–21.1)
t½,z 14.6 (9.6–22.7)
1 Median (5% Centile–95% Centile)

Example 4: Compute terminal half-live based on data

nca <- NCAMetrics(x=campsis, variable="Y") %>%
  add(c(Thalf(x=campsis %>% timerange(7*24, 10*24)))) %>%
  calculate()

table <- NCAMetricsTable() %>%
  add(nca)
table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric N = 2001
t½ 14.5 (9.7–22.1)
1 Median (5% Centile–95% Centile)

Example 5: Round your PK metrics

# Day 1
ncaD1 <- NCAMetrics(x=campsis %>% timerange(0, 24), variable="Y", scenario=c(day="Day 1")) %>%
  add(AUC(digits=~style_sigfig(.x, 2), name="AUC1")) %>% # At least 2 significant figures (default in gtsummary)
  add(AUC(digits=c(1,2,2), name="AUC2")) %>%             # Respectively 1/2/2 digit(s) after comma for med, p5 and p95
  add(AUC(digits=~signif(.x, 2), name="AUC3")) %>%       # 2 significant digits only
  add(AUC(digits=list(~plyr::round_any(.x, 5),
                      ~round(.x, 1) ,
                      ~style_number(.x)), name="AUC4")) %>% # 1 specific function for med, p5 and p95
  campsisnca::calculate()

# Day 7 
ncaD7 <- NCAMetrics(x=campsis %>% timerange(144, 168, rebase=TRUE), variable="Y", scenario=c(day="Day 7")) %>%
  add(AUC(name="AUC1")) %>%
  add(AUC(name="AUC2")) %>%
  add(AUC(name="AUC3")) %>%
  add(AUC(name="AUC4")) %>%
  campsisnca::calculate()

table <- NCAMetricsTable() %>%
  add(c(ncaD1, ncaD7))
  
table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric Day 1
N = 200
1
Day 7
N = 200
1
AUC1 134 (102–168) 199 (131–297)
AUC2 134.0 (102.03–167.51) 199.4 (130.64–296.69)
AUC3 130 (100–170) 200 (130–300)
AUC4 135 (102–168) 200 (130.6–297)
1 Median (5% Centile–95% Centile)

Example 6: Export custom metrics (including categorical data)

# Compute Cmax yourself using campsisnca
custom1 <- CustomMetric(fun=~Cmax() %>% iValue(.x, .y), name="Cmax custom", unit="ng/mL")

# Check if Cmax if higher than 12 ng/mL
custom2 <- CustomMetric(fun=~(Cmax() %>% iValue(.x, .y)) > 12, name="Cmax > 12", unit="%", categorical=TRUE)

# Shortcut notation is also accepted
custom3 <- CustomMetric(fun=~Cmax > 13, name="Cmax > 13", unit="%", categorical=TRUE)


# Day 1
ncaD1 <- NCAMetrics(x=campsis %>% timerange(0, 24), variable="Y", scenario=c(day="Day 1")) %>%
  add(c(Cmax(unit="ng/mL"), Tmax(unit="h"), custom1, custom2, custom3)) %>%
  campsisnca::calculate()

# Day 7 
ncaD7 <- NCAMetrics(x=campsis %>% timerange(144, 168, rebase=TRUE), variable="Y", scenario=c(day="Day 7")) %>%
  add(c(Cmax(), Tmax(), custom1, custom2, custom3)) %>%
  campsisnca::calculate()

table <- NCAMetricsTable() %>%
  add(c(ncaD1, ncaD7))

table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric Day 1
N = 200
1
Day 7
N = 200
1
Cmax (ng/mL) 10.2 (7.8–13.1) 14.8 (10.4–20.6)
tmax (h) 2.00 (1.00–6.00) 2.00 (1.00–6.00)
Cmax custom (ng/mL) 10.2 (7.8–13.1) 14.8 (10.4–20.6)
Cmax > 12 (%) 31 / 200 (16%) 164 / 200 (82%)
Cmax > 13 (%) 12 / 200 (6.0%) 149 / 200 (75%)
1 Median (5% Centile–95% Centile); n / N (%)
# Alternatively, all dichotomous levels can be shown as well:
table %>% export(dest="gt", subscripts=TRUE, all_dichotomous_levels=TRUE) %>% as_raw_html()
Metric Day 1
N = 200
1
Day 7
N = 200
1
Cmax (ng/mL) 10.2 (7.8–13.1) 14.8 (10.4–20.6)
tmax (h) 2.00 (1.00–6.00) 2.00 (1.00–6.00)
Cmax custom (ng/mL) 10.2 (7.8–13.1) 14.8 (10.4–20.6)
Cmax > 12 (%)

    FALSE 169 / 200 (85%) 36 / 200 (18%)
    TRUE 31 / 200 (16%) 164 / 200 (82%)
Cmax > 13 (%)

    FALSE 188 / 200 (94%) 51 / 200 (26%)
    TRUE 12 / 200 (6.0%) 149 / 200 (75%)
1 Median (5% Centile–95% Centile); n / N (%)

Example 7: Geometric mean / Geometric CV

nca <- NCAMetrics(x=campsis, variable="Y") %>%
  add(c(AUC(unit="ng/mL*h", stat_display="{geomean} ({geocv}%)"), Cavg(unit="ng/mL", stat_display="{geomean} ({geocv}%)"))) %>%
  calculate()

table <- NCAMetricsTable() %>%
  add(nca)
  
table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric N = 2001
AUC (ng/mL*h) 909 (35%)
Cavg (ng/mL) 3.79 (35.17%)
1 Geometric Mean (Geometric CV%)

Example 8: Statistics on categorical data with more than 2 levels

  getCategory <- function(.x, .y) {
    values <- Cmax() %>% iValue(.x, .y)
    retValue <- dplyr::case_when(
      values < 10 ~ "(1) < 10 ng/mL",
      values >= 10 & values <= 15 ~ "(2) 10-15 ng/mL",
      values > 15 ~ "(3) > 15 ng/mL",
    )
    return(retValue)
  }

  # Or equivalently, the 1-line purrr-style lambda expression
  # getCategory <- ~case_when(Cmax < 10 ~ "(1) < 10 ng/mL", Cmax >= 10 & Cmax <= 15 ~ "(2) 10-15 ng/mL", Cmax > 15 ~ "(3) > 15 ng/mL")

  # Day 1
  ncaD1 <- NCAMetrics(x=campsis %>% timerange(0, 24), variable="Y", scenario=c(day="Day 1")) %>%
    add(c(Cmax(unit="ng/mL"), CustomMetric(fun=getCategory, name="Cmax categories", unit="%", categorical=TRUE))) %>%
    campsisnca::calculate()
  
  # Day 7 
  ncaD7 <- NCAMetrics(x=campsis %>% timerange(144, 168, rebase=TRUE), variable="Y", scenario=c(day="Day 7")) %>%
    add(c(Cmax(), CustomMetric(fun=getCategory, name="Cmax categories", unit="%", categorical=TRUE))) %>%
    campsisnca::calculate()
  
  table <- NCAMetricsTable()  
  table <- table %>%
    add(c(ncaD1, ncaD7))
  
table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric Day 1
N = 200
1
Day 7
N = 200
1
Cmax (ng/mL) 10.2 (7.8–13.1) 14.8 (10.4–20.6)
Cmax categories (%)

    (1) < 10 ng/mL 87 / 200 (44%) 6 / 200 (3.0%)
    (2) 10-15 ng/mL 111 / 200 (56%) 96 / 200 (48%)
    (3) > 15 ng/mL 2 / 200 (1.0%) 98 / 200 (49%)
1 Median (5% Centile–95% Centile); n / N (%)

Example 9: Time above or below a certain threshold

In the example below, we look at the individual time above (or below) 10 ng/mL at Day 1 for the 10 first subjects.

day1 <- campsis %>%
  timerange(0, 24) %>%
  dplyr::filter(ID %in% (1:10))

campsis::spaghettiPlot(day1 , "Y") +
  ggplot2::geom_hline(yintercept=10, linetype="dashed", color="red")

nca <- NCAMetrics(x=day1, variable="Y") %>%
  add(c(Cmax(unit="ng/mL*h", stat_display="{mean}"),
        TimeAboveLimit(limit=10, unit="h", stat_display="{mean}"),
        TimeBelowLimit(limit=10, unit="h", stat_display="{mean}"))) %>%
  calculate()

table <- NCAMetricsTable() %>%
  add(nca)
  
table %>% export(dest="dataframe", type="individual_wide")
## # A tibble: 10 × 4
##       id  Cmax `Time above 10` `Time below 10`
##    <dbl> <dbl>           <dbl>           <dbl>
##  1     1  9.78           0                24  
##  2     2  6.11           0                24  
##  3     3 10.9            0.829            23.2
##  4     4  9.72           0                24  
##  5     5 10.1            0.427            23.6
##  6     6 10.1            0.186            23.8
##  7     7  9.28           0                24  
##  8     8 13.7            4.94             19.1
##  9     9  9.62           0                24  
## 10    10  9.91           0                24

Summary statistics can also be exported:

table %>% export(dest="gt", subscripts=TRUE) %>% as_raw_html()
Metric N = 101
Cmax (ng/mL*h) 9.93
Time above 10 (h) 0.64
Time below 10 (h) 23.36
1 Mean

About

Non-compartmental analysis on CAMPSIS simulation output

Resources

License

Stars

Watchers

Forks

Packages

No packages published