Creation of these materials were partially supported by funding from the Metrum Research Group.
PKNCA is a tool for calculating noncompartmental analysis (NCA) results for pharmacokinetic (PK) data.
… but, you already knew that or you wouldn’t be here.
PKNCA has several foci:
I hope that you have a whale of a good time during this training.
![]()
(Foreshadowing…)
“Tidy datasets… have a specific structure: each variable is a column, each observation is a row, and each type of observational unit is a table.” - Hadley Wickham (https://doi.org/10.18637/jss.v059.i10)
CDISC has NCA tidied, and PKNCA follows that model:
PKNCAconc()
object)PKNCAdose()
object)pk.nca()
output)PKNCA requires at least the concentration, time, and what you want to calculate.
Column names are provided by the input to PKNCAconc()
and PKNCAdose(); they are not hard-coded.
Columns that can be used include:
PKNCAconc(): concentration, time, groups; data
exclusions; half-life inclusion and exclusionPKNCAdose(): dose, time, groups; route, rate/duration
of infusion; data exclusionsPKNCAdata(): groups, start, end, and
any NCA parameters to calculateIn the following slides, abbreviated data from an example study where two treatments (“A” and “B”) are administered to two subjects (1 and 2).
/, if
/ is present)....|Treatment+Subject), PKNCA
automatically knows to keep Treatment and drop
Subject for summaries (more on that later).| Subject | Treatment | Time | Conc |
|---|---|---|---|
| 1 | A | 0 | 0 |
| 1 | A | 2 | 2.143 |
| 1 | A | 8 | 0.4696 |
| 1 | B | 0 | 0 |
| 1 | B | 2 | 2.179 |
| 1 | B | 8 | 0.4852 |
| Subject | Treatment | Time | Conc |
|---|---|---|---|
| 2 | A | 0 | 0 |
| 2 | A | 2 | 1.937 |
| 2 | A | 8 | 0.4929 |
| 2 | B | 0 | 0 |
| 2 | B | 2 | 2.127 |
| 2 | B | 8 | 0.4804 |
| Subject | Treatment | Time | Dose |
|---|---|---|---|
| 1 | A | 0 | 10 |
| 1 | B | 0 | 10 |
| Subject | Treatment | Time | Dose |
|---|---|---|---|
| 2 | A | 0 | 10 |
| 2 | B | 0 | 10 |
| start | end | cmax | tmax | auclast |
|---|---|---|---|---|
| 0 | 8 | TRUE | TRUE | TRUE |
Groups are not required, if you want the same intervals calculated for each group.
library(dplyr)
library(ggplot2)
library(tidyr)
library(purrr)
library(PKNCA)
# Concentration data setup
d_conc <-
datasets::Theoph %>%
filter(Subject %in% 1)
o_conc <- PKNCAconc(conc~Time, data=d_conc)
# Setup intervals for calculation
d_intervals <- data.frame(start=0, end=24, cmax=TRUE, tmax=TRUE,
auclast=TRUE, aucint.inf.obs=TRUE)
# Combine concentration and dose
o_data <- PKNCAdata(o_conc, intervals=d_intervals)
# Calculate the results (suppressMessages() hides a message that isn't needed now)
o_result <- suppressMessages(pk.nca(o_data))
# summary(o_result)PKNCAconc(): define a concentration-time
PKNCAconc object
PKNCAdose(): define a dose-time PKNCAdose
object (optional)
PKNCAdata(): combine PKNCAconc, optionally
PKNCAdose, and optionally intervals into a
PKNCAdata object
PKNCAconc object must be given; the
PKNCAdose object is optional; interval definitions are
usually given; calculation options may be givenpk.nca(): calculate the NCA parameters from a data
object into a PKNCAresults objectWe will break this down in subsequent slides.
# Concentration data setup
d_conc <-
datasets::Theoph %>%
filter(Subject %in% 1)
o_conc <- PKNCAconc(conc~Time, data=d_conc)
# Dose data setup
d_dose <-
datasets::Theoph %>%
filter(Subject %in% 1) %>%
filter(Time == 0)
o_dose <- PKNCAdose(Dose~Time, data=d_dose)
# Combine concentration and dose
o_data <- PKNCAdata(o_conc, o_dose)
# Calculate the results
o_result <- pk.nca(o_data)# Load your dataset as a data.frame
d_conc <-
datasets::Theoph %>%
filter(Subject %in% 1)
# Take a look at the data
pander::pander(head(d_conc, 2))| Subject | Wt | Dose | Time | conc |
|---|---|---|---|---|
| 1 | 79.6 | 4.02 | 0 | 0.74 |
| 1 | 79.6 | 4.02 | 0.25 | 2.84 |
# Load your dataset as a data.frame
d_dose <-
datasets::Theoph %>%
filter(Subject %in% 1) %>%
filter(Time == 0)
# Take a look at the data
pander::pander(d_dose)| Subject | Wt | Dose | Time | conc |
|---|---|---|---|---|
| 1 | 79.6 | 4.02 | 0 | 0.74 |
To calculate summary statistics, use summary(); to
extract all individual-level results, use
as.data.frame().
The "caption" attribute of the summary describes how the
summary statistics were calculated for each parameter. (Hint:
pander::pander() knows how to use that to put the caption
on a table in a report.)
The individual results contain the columns for start time, end time, grouping variables (none in this example), parameter names, values, and if the value should be excluded.
| start | end | auclast | cmax | tmax | tlag | count_conc | half.life |
|---|---|---|---|---|---|---|---|
| 0 | Inf | 147 | 10.5 | 1.12 | 0.000 | 11.0 | 14.3 |
| aucinf.obs | aucpext.obs | cl.obs |
|---|---|---|
| 215 | 31.5 | 0.0187 |
Use as.data.frame() to get the individual NCA parameter
results.
| start | end | PPTESTCD | PPORRES | PPANMETH | exclude |
|---|---|---|---|---|---|
| 0 | Inf | auclast | 147.2 | Imputation: start_predose_conc0. AUC: lin up/log down | NA |
| 0 | Inf | cmax | 10.5 | Imputation: start_predose_conc0 | NA |
| 0 | Inf | tmax | 1.12 | Imputation: start_predose_conc0 | NA |
Three types of data are inputs for calculation in PKNCA:
PKNCAconc),PKNCAdose), andPKNCAconc and PKNCAdose objects can
optionally have groups. The groups in a PKNCAdose object
must be the same or fewer than the groups in PKNCAconc
object (for example, all subjects in a treatment arm may receive the
same dose).
A group separates one full concentration-time profile for a subject that you may ever want to consider at the same time. Usually, it groups by study, treatment, analyte, and subject (other groups can be useful depending on the study design).
An interval selects a time range within a group.
One time can be in zero or more intervals, but only zero or one group. Intervals can be adjacent (0-12 and 12-24) or overlap (0-12 and 0-24). In other words, one sample may be used in more than one interval, but one sample will never be used in more than one group.
Legend: The group contains all points on the figure. Shaded regions indicate intervals. Arrows indicate points shared between intervals within the group.
PKNCAconc (if given to
PKNCAdose, it must not be missing).NA).Columns must be created for:
![]()
Group: 🗸
a pod of killer whales
Normal dosing data setup:
PKNCAdose(dose~time|actarm+usubjid, data=d_dose)
PKNCAdose(~time|actarm+usubjid, data=d_dose)PKNCAdose(dose~.|actarm+usubjid, data=d_dose)PKNCAdose(dose~time|actarm, data=d_dose)PKNCAdose(dose~.|actarm, data=d_dose)PKNCAdose(~time|actarm, data=d_dose)Intervals have columns for:
start and end times for the interval,TRUE means to calculate it;
FALSE means don’t). The full list of available parameters
is in the selection
of calculation intervals vignette.
| start | end | auclast | cmax | tmax | half.life | aucinf.obs |
|---|---|---|---|---|---|---|
| 0 | 24 | TRUE | FALSE | FALSE | FALSE | FALSE |
| 0 | Inf | FALSE | TRUE | TRUE | TRUE | TRUE |
o_conc <- PKNCAconc(conc~Time|Treatment+Subject, data=d_conc)
try({
o_data <- PKNCAdata(o_conc)
summary(pk.nca(o_data))
})## Error in PKNCAdata.default(data.conc = data.conc, data.dose = data.dose, :
## If data.dose is not given, intervals must be given
Whoops! Without dosing, we need intervals.
o_conc <- PKNCAconc(conc~Time|Treatment+Subject, data=d_conc)
d_intervals <- data.frame(start=0, end=Inf, cmax=TRUE, tmax=TRUE,
half.life=TRUE, aucinf.obs=TRUE)
o_data_manual_intervals <- PKNCAdata(o_conc, intervals=d_intervals)
summary(pk.nca(o_data_manual_intervals))## start end Treatment N cmax tmax half.life aucinf.obs
## 0 Inf High dose 5 9.16 [19.4] 3.48 [0.980, 3.55] 7.73 [1.08] 120 [26.2]
## 0 Inf Low dose 7 8.30 [15.2] 1.12 [0.630, 2.02] 8.50 [2.67] 111 [31.6]
##
## Caption: cmax, aucinf.obs: geometric mean and geometric coefficient of variation; tmax: median and range; half.life: arithmetic mean and standard deviation; N: number of subjects
o_conc <- PKNCAconc(conc~Time|Treatment+Subject, data=d_conc)
o_dose <- PKNCAdose(Dose~dose_time|Treatment+Subject, data=d_dose)
o_data_auto_intervals <- PKNCAdata(o_conc, o_dose)
o_data_auto_intervals$intervals$aucint.inf.obs <- TRUE
summary(pk.nca(o_data_auto_intervals))## start end Treatment N auclast cmax tmax
## 0 Inf Low dose 7 94.5 [22.8] 8.30 [15.2] 1.12 [0.630, 2.02]
## 0 Inf High dose 5 105 [23.1] 9.16 [19.4] 3.48 [0.980, 3.55]
## tlag count_conc half.life aucinf.obs aucint.inf.obs
## 0.000 [0.000, 0.000] 11.0 [11.0, 11.0] 8.50 [2.67] 111 [31.6] 111 [31.6]
## 0.000 [0.000, 0.000] 11.0 [11.0, 11.0] 7.73 [1.08] 120 [26.2] 120 [26.2]
## aucpext.obs cl.obs
## 14.6 [7.82] 0.0370 [34.1]
## 12.8 [4.08] 0.0440 [20.5]
##
## Caption: auclast, cmax, aucinf.obs, aucint.inf.obs, cl.obs: geometric mean and geometric coefficient of variation; tmax, tlag, count_conc: median and range; half.life, aucpext.obs: arithmetic mean and standard deviation; N: number of subjects
The considerations below mainly apply to actual-time data; nominal-time data usually have measurements at the start and end time for the interval.
With an interval start and end of 0 and 24 (and the last measurement time just after 24 hours):
The considerations below mainly apply to actual-time data; nominal-time data usually have measurements at the start and end time for the interval.
With an interval start and end of 0 and 24 (and the last measurement time just after 24 hours):
The considerations below mainly apply to actual-time data; nominal-time data usually have measurements at the start and end time for the interval.
With an interval start and end of 0 and 24 (and the last measurement time just after 24 hours):
end=Inf).The data for the exercise are from a PK study of amikacin in a killer whale and a beluga whale. (DOI: 10.1638/03-078)
![]()
(Callback…)
library(PKNCA)
# Data available from https://github.com/humanpred/pknca/tree/main/data-raw/whale
d_conc <- read.csv("c:/tmp/whale_conc.csv")
d_dose <- read.csv("c:/tmp/whale_dose.csv")
head(d_conc)
head(d_dose)
o_conc <- PKNCAconc(concentration~time|Animal, data=d_conc)
o_dose <- PKNCAdose(dose~time|Animal, data=d_dose)
o_data <- PKNCAdata(o_conc, o_dose)
o_data$intervals
o_nca <- pk.nca(o_data)
summary(o_nca)
summary(o_nca, drop.group=c())
as.data.frame(o_nca)Data may be included/excluded in two ways:
For both ways of including/excluding data, it is defined by a column in the input data:
exclude column is text: NA or
an empty string ("") keeps the row, and any other text
excludes it (the text is the reason for exclusion).exclude_half.life and
include_half.life columns are logical: TRUE
marks the point, and FALSE or NA does
not.Use the exclude argument for PKNCAconc() or
PKNCAdose().
When you use exclude, this is how you give your data to
PKNCA:
d_before_exclude <-
data.frame(
time=0:4,
conc=c(0, 2, 1, 0.5, 0.25),
not_this=c(NA, "Not this", rep(NA, 3))
)
o_conc <-
PKNCAconc(
data=d_before_exclude,
conc~time,
exclude="not_this"
)
And, this is how PKNCA thinks about it:
| time | conc | not_this |
|---|---|---|
| 0 | 0 | NA |
| 2 | 1 | NA |
| 3 | 0.5 | NA |
| 4 | 0.25 | NA |
allow.tmax.in.half.life=TRUE) to
tlast and excluding BLQ in the middle.min.hl.points option) to
tlast.
adj.r.squared.factor).
r.squared.factor to a tolerance to select on the
unadjusted r2 instead; that takes
adj.r.squared.factor out of use.> 0.Only points after the last dose administration are considered (since
PKNCA 0.12.1), and a censored-likelihood (Tobit) estimation method is
available with hl_method = "tobit" (development
version).
Note: WinNonlin first requires λz> 0 then selects for
adjusted r2. Therefore, WinNonlin will occasionally provide a
half-life when PKNCA will not, but the fit line is not as good (as
measured by r2). The selection of filtering order is an
intentional feature with PKNCA, and it generally has minimal impact on
summary statistics because the quality of the half-life fit is usually
low in this scenario.
Use the exclude_half.life or
include_half.life argument for PKNCAconc().
The two arguments behave very differently in how points are selected for
half-life.
exclude_half.life uses the same automatic point
selection method of curve stripping (described before), but it excludes
individual points from that calculation.
include_half.life uses no automatic point selection
method, and only points specifically noted by the analyst are
included.
d_urine <-
data.frame(
conc=c(1, 2, 3),
urine_volume=c(200, 100, 300),
time=c(1, 2, 3)
)
o_conc <- PKNCAconc(data=d_urine, conc~time, volume="urine_volume")
d_intervals <- data.frame(start=0, end=24, ae=TRUE)
o_data <- PKNCAdata(o_conc, intervals=d_intervals)
o_nca <- suppressMessages(pk.nca(o_data))
summary(o_nca)## start end ae
## 0 24 1300
##
## Caption: ae: geometric mean and geometric coefficient of variation
Intervals for urine are treated the same as any other interval type. Specifically, PKNCA does not look outside the start and end of the interval.
If you don’t need a parameter, PKNCA won’t calculate it.
For example, if all you need is cmax, all you’ll get is
cmax.
o_conc <- PKNCAconc(data=data.frame(conc=2^-(1:4), time=0:3), conc~time)
o_data <- PKNCAdata(o_conc, intervals=data.frame(start=0, end=Inf, cmax=TRUE))
o_nca <- suppressMessages(pk.nca(o_data))
as.data.frame(o_nca)## # A tibble: 1 × 6
## start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 0 Inf cmax 0.5 "" <NA>
If you need AUC0-\(\infty\), PKNCA will calculate other required parameters behind the scenes.
o_data <-
PKNCAdata(
o_conc,
intervals=
data.frame(
start=0, end=Inf,
aucinf.obs=TRUE
)
)
o_nca <- suppressMessages(pk.nca(o_data))
## # A tibble: 14 × 6
## start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 0 Inf tmax 0 "" <NA>
## 2 0 Inf tlast 3 "" <NA>
## 3 0 Inf clast.obs 0.0625 "" <NA>
## 4 0 Inf lambda.z 0.693 "" <NA>
## 5 0 Inf r.squared 1 "" <NA>
## 6 0 Inf adj.r.squared 1 "" <NA>
## 7 0 Inf lambda.z.corrxy -1 "" <NA>
## 8 0 Inf lambda.z.time.first 1 "" <NA>
## 9 0 Inf lambda.z.time.last 3 "" <NA>
## 10 0 Inf lambda.z.n.points 3 "" <NA>
## 11 0 Inf clast.pred 0.0625 "" <NA>
## 12 0 Inf half.life 1 "" <NA>
## 13 0 Inf span.ratio 2 "" <NA>
## 14 0 Inf aucinf.obs 0.721 "AUC: lin up/log down" <NA>
CDISC has one set of names, but they are not precise (e.g. AUCINT doesn’t tell the interpolation/extrapolation method).
PKNCA tries to be everything to everyone (in terms of parameters calculated), and it simultaneously tries to be precise. That yields many parameters.
See the Selection of Calculation Intervals vignette in the Parameters Available for Calculation in an Interval section for all available parameters.
Very few parameters reach outside of the start and
end of an interval for additional information about what is
being calculated. The only parameters that look outside are the
aucint and aumcint classes of parameters.
AUCint may look after the end of the interval to calculate
the concentration at end.
When dosing data are given, it stops at the first dose at or after the end of the interval, so a concentration measured after that dose is not interpolated back into the interval (e.g. a dose at 24 hours but the prior sample is around 12 and the next is around 25):
A simple way to exclude a value from results is to convert the results to a data.frame and then drop the rows you don’t want:
## # A tibble: 13 × 6
## start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 0 Inf tmax 0 "" <NA>
## 2 0 Inf tlast 3 "" <NA>
## 3 0 Inf clast.obs 0.0625 "" <NA>
## 4 0 Inf lambda.z 0.693 "" <NA>
## 5 0 Inf r.squared 1 "" <NA>
## 6 0 Inf adj.r.squared 1 "" <NA>
## 7 0 Inf lambda.z.corrxy -1 "" <NA>
## 8 0 Inf lambda.z.time.first 1 "" <NA>
## 9 0 Inf lambda.z.time.last 3 "" <NA>
## 10 0 Inf lambda.z.n.points 3 "" <NA>
## 11 0 Inf clast.pred 0.0625 "" <NA>
## 12 0 Inf span.ratio 2 "" <NA>
## 13 0 Inf aucinf.obs 0.721 "AUC: lin up/log down" <NA>
But, parameters derived from half-life remain.
When you use the exclude() function, parameters that are
dependent on an excluded parameter will be excluded.
## # A tibble: 14 × 6
## start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 0 Inf tmax 0 "" <NA>
## 2 0 Inf tlast 3 "" <NA>
## 3 0 Inf clast.obs 0.0625 "" <NA>
## 4 0 Inf lambda.z 0.693 "" span.ratio < 3
## 5 0 Inf r.squared 1 "" span.ratio < 3
## 6 0 Inf adj.r.squared 1 "" span.ratio < 3
## 7 0 Inf lambda.z.corrxy -1 "" span.ratio < 3
## 8 0 Inf lambda.z.time.first 1 "" span.ratio < 3
## 9 0 Inf lambda.z.time.last 3 "" span.ratio < 3
## 10 0 Inf lambda.z.n.points 3 "" span.ratio < 3
## 11 0 Inf clast.pred 0.0625 "" span.ratio < 3
## 12 0 Inf half.life 1 "" span.ratio < 3
## 13 0 Inf span.ratio 2 "" span.ratio < 3
## 14 0 Inf aucinf.obs 0.721 "AUC: lin up/log down" span.ratio < 3
Now, everything dependent on the half-life is excluded in summaries.
## start end aucinf.obs
## 0 Inf 0.721
##
## Caption: aucinf.obs: geometric mean and geometric coefficient of variation
## start end aucinf.obs
## 0 Inf NC
##
## Caption: aucinf.obs: geometric mean and geometric coefficient of variation; NC: not calculated
Generate all individual profiles using the groups that you defined:
Make summary tables using the summary() function on the
NCA results, and use pander::pander() to make a pretty
table with captions.
| start | end | aucinf.obs |
|---|---|---|
| 0 | Inf | 0.721 |
Make an NCA data listing using the as.data.frame()
function on the NCA results.
PKNCA supports units with the pknca_units_table()
function. See the Unit
Assignment and Conversion with PKNCA vignette for more
information.
When units are not specified, The most common place where that becomes an issue is with clearance which ends up having unusual units like “mg/(hr*ng/mL)” (with units of mg for dosing, hr for time, and ng/mL for concentration).
Some data points are required for inputs such as:
Due to the need for back-extrapolation to C0, AUCs for IV
bolus dosing need to use different AUC parameters such as
"aucivlast" instead of "auclast".
Sparse NCA calculations are supported in PKNCA. See the Sparse NCA Calculations vignette for more information.
PKNCA does not (yet) have the ability to calculate secondary PK parameters that require looking at more than one group/interval at a time.
PKNCA has an extensive testing and validation suite built-in. To run the testing and validation suite of tests with a full report generated, see the PKNCA Validation vignette.
d_conc <-
datasets::Theoph %>%
rename(time=Time) %>%
mutate(
Subject=as.character(Subject)
)
d_multidose <-
PKNCAconc(conc~time|Subject, data=d_conc) %>%
superposition(tau=24, check.blq=FALSE)
d_singledose_single_analyte <-
d_conc %>%
mutate(
Study_Part="Single"
)
d_multidose_single_analyte <-
d_conc %>%
mutate(Day=1) %>%
bind_rows(
d_multidose %>% mutate(time=time + 120, Day=6)
) %>%
mutate(
Study_Part="Multiple"
)o_conc <- PKNCAconc(data=d_single_multi_conc, conc~time|Study_Part+Subject)
o_dose <- PKNCAdose(data=d_single_multi_dose, Dose~time|Study_Part+Subject)
o_data <- PKNCAdata(o_conc, o_dose)
o_data$intervals %>% select(-Subject) %>% unique() %>% as.data.frame()## start end auclast auclast_se auclast_df aucall aucall_se aucall_df aumclast
## 1 0 Inf TRUE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 0 120 TRUE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 120 144 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## aumclast_se aumclast_df aumcall aumcall_se aumcall_df aucint.last aucint.all
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE TRUE FALSE
## aumcint.last aumcint.all c0 cmax cmin tmax tmin tlast tfirst clast.obs
## 1 FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
## cl.last cl.all cl.int.all cl.int.last mrt.last mrt.all mrt.int.all
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## mrt.int.last mrt.iv.last vss.last vss.iv.last vss.all vss.int.all
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## vss.int.last cav cav.int.last cav.int.all ctrough cstart ptr tlag
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
## 3 FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE
## deg.fluc swing ceoi aucabove.predose.all aucabove.trough.all count_conc
## 1 FALSE FALSE FALSE FALSE FALSE TRUE
## 2 FALSE FALSE FALSE FALSE FALSE TRUE
## 3 FALSE FALSE FALSE FALSE FALSE TRUE
## count_conc_measured totdose volpk ae clr.last clr.obs clr.pred fe
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## ertlst ermax ertmax erint erlst ratio.cmax ratio.auclast ratio.aucint.last
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## ratio.aucint.all sparse_auclast sparse_auc_se sparse_auc_df sparse_aumclast
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## sparse_aumc_se sparse_aumc_df time_above aucivlast aucivlast_se aucivlast_df
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## aucivall aucivall_se aucivall_df aucivint.last aucivint.all aucivpbextlast
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## aucivpbextall aucivpbextint.last aucivpbextint.all aumcivlast aumcivlast_se
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## aumcivlast_df aumcivall aumcivall_se aumcivall_df aumcivint.last
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## aumcivint.all half.life r.squared adj.r.squared lambda.z.corrxy lambda.z
## 1 FALSE TRUE FALSE FALSE FALSE FALSE
## 2 FALSE TRUE FALSE FALSE FALSE FALSE
## 3 FALSE TRUE FALSE FALSE FALSE FALSE
## lambda.z.time.first lambda.z.time.last lambda.z.n.points clast.pred
## 1 FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE
## span.ratio tobit_residual adj_tobit_residual lambda.z.n.points_blq
## 1 FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE
## thalf.eff.last thalf.eff.iv.last kel.last kel.iv.last kel.all kel.int.all
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## kel.int.last cl.iv.all cl.iv.last cl.ivint.all cl.ivint.last cl.sparse.last
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## f.last f.int.last f.int.all mrt.sparse.last mrt.iv.all mrt.ivint.all
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## mrt.ivint.last vz.all vz.int.all vz.int.last vz.iv.all vz.iv.last
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## vz.ivint.all vz.ivint.last vz.last vss.iv.all vss.ivint.all vss.ivint.last
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## vss.sparse.last aucinf.obs aucinf.obs_se aucinf.obs_df aucinf.pred
## 1 FALSE TRUE FALSE FALSE FALSE
## 2 FALSE TRUE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## aumcinf.obs aumcinf.obs_se aumcinf.obs_df aumcinf.pred aucint.inf.obs
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE TRUE
## aucint.inf.pred aumcint.inf.obs aumcint.inf.pred aucivinf.obs aucivinf.obs_se
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## aucivinf.obs_df aucivinf.pred aucivpbextinf.obs aucivpbextinf.pred
## 1 FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE
## aumcivinf.obs aumcivinf.obs_se aumcivinf.obs_df aumcivinf.pred aucpext.obs
## 1 FALSE FALSE FALSE FALSE TRUE
## 2 FALSE FALSE FALSE FALSE TRUE
## 3 FALSE FALSE FALSE FALSE FALSE
## aucpext.pred kel.iv.all kel.ivint.all kel.ivint.last kel.sparse.last cl.obs
## 1 FALSE FALSE FALSE FALSE FALSE TRUE
## 2 FALSE FALSE FALSE FALSE FALSE TRUE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## cl.pred cl.int.inf.obs cl.int.inf.pred cl.iv.obs cl.iv.pred f.obs f.pred
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE TRUE FALSE FALSE FALSE FALSE FALSE
## f.int.obs f.int.pred mrt.obs mrt.pred mrt.int.inf.obs mrt.int.inf.pred
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## mrt.iv.obs mrt.iv.pred mrt.md.obs mrt.md.pred mrt.ivmd.obs mrt.ivmd.pred
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## vz.obs vz.pred vz.int.inf.obs vz.int.inf.pred vz.iv.obs vz.iv.pred
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## vz.sparse.last vss.obs vss.pred vss.iv.obs vss.iv.pred vss.md.obs vss.md.pred
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## vss.ivmd.obs vss.ivmd.pred vss.int.inf.obs vss.int.inf.pred cav.int.inf.obs
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## cav.int.inf.pred ratio.aucinf.obs ratio.aucinf.pred thalf.eff.obs
## 1 FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE
## thalf.eff.pred thalf.eff.iv.obs thalf.eff.iv.pred kel.obs kel.pred kel.iv.obs
## 1 FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE
## kel.iv.pred kel.int.inf.obs kel.int.inf.pred auclast.dn aucall.dn
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## aucinf.obs.dn aucinf.pred.dn aumclast.dn aumcall.dn aumcinf.obs.dn
## 1 FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE
## aumcinf.pred.dn cmax.dn cmin.dn clast.obs.dn clast.pred.dn cav.dn ctrough.dn
## 1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## 3 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## clr.last.dn clr.obs.dn clr.pred.dn Study_Part impute
## 1 FALSE FALSE FALSE Single start_predose_conc0
## 2 FALSE FALSE FALSE Multiple start_predose_conc0
## 3 FALSE FALSE FALSE Multiple start_cmin
d_intervals <-
data.frame(
start=0,
end=24,
Subject=c("1", "2"),
Study_Part="Single",
aucinf.obs=TRUE
)
o_data <- PKNCAdata(o_conc, o_dose, intervals=d_intervals)
o_nca <- pk.nca(o_data)## Warning: Study_Part=Single; Subject=3: No intervals for data
## Warning: Study_Part=Single; Subject=4: No intervals for data
## Warning: Study_Part=Single; Subject=5: No intervals for data
## Warning: Study_Part=Single; Subject=6: No intervals for data
## Warning: Study_Part=Single; Subject=7: No intervals for data
## Warning: Study_Part=Single; Subject=8: No intervals for data
## Warning: Study_Part=Single; Subject=9: No intervals for data
## Warning: Study_Part=Single; Subject=10: No intervals for data
## Warning: Study_Part=Single; Subject=11: No intervals for data
## Warning: Study_Part=Single; Subject=12: No intervals for data
## Warning: Study_Part=Multiple; Subject=1: No intervals for data
## Warning: Study_Part=Multiple; Subject=2: No intervals for data
## Warning: Study_Part=Multiple; Subject=3: No intervals for data
## Warning: Study_Part=Multiple; Subject=4: No intervals for data
## Warning: Study_Part=Multiple; Subject=5: No intervals for data
## Warning: Study_Part=Multiple; Subject=6: No intervals for data
## Warning: Study_Part=Multiple; Subject=7: No intervals for data
## Warning: Study_Part=Multiple; Subject=8: No intervals for data
## Warning: Study_Part=Multiple; Subject=9: No intervals for data
## Warning: Study_Part=Multiple; Subject=10: No intervals for data
## Warning: Study_Part=Multiple; Subject=11: No intervals for data
## Warning: Study_Part=Multiple; Subject=12: No intervals for data
## start end Study_Part N aucinf.obs
## 0 24 Single 2 144 [69.0]
##
## Caption: aucinf.obs: geometric mean and geometric coefficient of variation; N: number of subjects
# Find the time closest to 12 hours
d_intervals_prep <-
d_single_multi_conc %>%
filter(Study_Part == "Single") %>%
mutate(
time_deviation=abs(time-12)
) %>%
group_by(Subject, Study_Part) %>%
filter(time %in% time[time_deviation == min(time_deviation)])
d_intervals <-
d_intervals_prep %>%
select(Study_Part, Subject, end=time) %>%
mutate(
start=0,
aucinf.obs=TRUE
)
o_data <- PKNCAdata(o_conc, o_dose, intervals=d_intervals)
o_nca <- pk.nca(o_data)## Warning: Study_Part=Multiple; Subject=1: No intervals for data
## Warning: Study_Part=Multiple; Subject=2: No intervals for data
## Warning: Study_Part=Multiple; Subject=3: No intervals for data
## Warning: Study_Part=Multiple; Subject=4: No intervals for data
## Warning: Study_Part=Multiple; Subject=5: No intervals for data
## Warning: Study_Part=Multiple; Subject=6: No intervals for data
## Warning: Study_Part=Multiple; Subject=7: No intervals for data
## Warning: Study_Part=Multiple; Subject=8: No intervals for data
## Warning: Study_Part=Multiple; Subject=9: No intervals for data
## Warning: Study_Part=Multiple; Subject=10: No intervals for data
## Warning: Study_Part=Multiple; Subject=11: No intervals for data
## Warning: Study_Part=Multiple; Subject=12: No intervals for data
## Warning: The `drop.group` argument of `summary.PKNCAresults()` is deprecated as of PKNCA
## 0.11.0.
## ℹ Please use the `drop_group` argument instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: drop.group including start or end may result in incorrect groupings
## (such as inaccurate comparison of intervals). Drop these with care.
## start Study_Part N aucinf.obs
## 0 Single 12 120 [29.5]
##
## Caption: aucinf.obs: geometric mean and geometric coefficient of variation; N: number of subjects
d_single_multi_conc_multi_analyte <-
bind_rows(
d_single_multi_conc %>% mutate(Analyte="Parent"),
d_single_multi_conc %>%
mutate(
Analyte="Metabolite",
conc=conc/2
)
)
o_conc <-
PKNCAconc(
data=d_single_multi_conc_multi_analyte,
conc~time|Study_Part+Subject/Analyte
)
o_dose <- PKNCAdose(data=d_single_multi_dose, Dose~time|Study_Part+Subject)
o_data <- PKNCAdata(o_conc, o_dose)
o_nca <- pk.nca(o_data)
summary(o_nca)## start end Study_Part Analyte N auclast aucint.last cmax
## 0 Inf Single Parent 12 98.7 [22.5] . 8.65 [17.0]
## 0 120 Multiple Parent 12 237 [38.0] . 8.65 [17.0]
## 120 144 Multiple Parent 12 . 115 [28.4] 10.0 [21.0]
## 0 Inf Single Metabolite 12 49.3 [22.5] . 4.32 [17.0]
## 0 120 Multiple Metabolite 12 118 [38.0] . 4.32 [17.0]
## 120 144 Multiple Metabolite 12 . 57.4 [28.4] 5.02 [21.0]
## tmax ctrough tlag count_conc half.life
## 1.14 [0.630, 3.55] . 0.000 [0.000, 0.000] 11.0 [11.0, 11.0] 8.18 [2.12]
## 1.14 [0.630, 3.55] . 0.000 [0.000, 0.000] 12.0 [12.0, 12.0] 71.1 [47.4]
## 1.09 [0.630, 3.55] NC 0.000 [0.000, 0.000] 12.0 [12.0, 12.0] 8.15 [2.13]
## 1.14 [0.630, 3.55] . 0.000 [0.000, 0.000] 11.0 [11.0, 11.0] 8.18 [2.12]
## 1.14 [0.630, 3.55] . 0.000 [0.000, 0.000] 12.0 [12.0, 12.0] 71.1 [47.4]
## 1.09 [0.630, 3.55] NC 0.000 [0.000, 0.000] 12.0 [12.0, 12.0] 8.15 [2.13]
## aucinf.obs aucint.inf.obs aucpext.obs cl.obs cl.int.inf.obs
## 115 [28.4] . 13.8 [6.34] 0.0398 [29.4] .
## 393 [72.5] . 37.7 [13.6] 0.0116 [74.7] .
## . 115 [28.4] . . NC
## 57.4 [28.4] . 13.8 [6.34] 0.0796 [29.4] .
## 197 [72.5] . 37.7 [13.6] 0.0232 [74.7] .
## . 57.4 [28.4] . . NC
##
## Caption: auclast, aucint.last, cmax, ctrough, aucinf.obs, aucint.inf.obs, cl.obs, cl.int.inf.obs: geometric mean and geometric coefficient of variation; tmax, tlag, count_conc: median and range; half.life, aucpext.obs: arithmetic mean and standard deviation; N: number of subjects; NC: not calculated