Introduction
Once a calculation is complete, the steps to extract the desired results from the results object are described below.
Setup
To extract results, first results must be available. The example below comes from the Introduction and Usage vignette and is reproduced here simply to have results available. See that vignette for more details about running PKNCA.
library(PKNCA)
suppressPackageStartupMessages(library(dplyr))
d_conc <-
as.data.frame(datasets::Theoph) %>%
mutate(Subject=as.numeric(as.character(Subject)))
## Generate the dosing data
d_dose <- d_conc[d_conc$Time == 0,]
d_dose$Time <- 0
conc_obj <-
PKNCAconc(
d_conc,
conc~Time|Subject
)
dose_obj <-
PKNCAdose(
d_dose,
Dose~Time|Subject
)
data_obj <- PKNCAdata(conc_obj, dose_obj)
results_obj <- pk.nca(data_obj)Modifying Results
Exclusion of Select Results
In many scenarios, individual results may need to be excluded from
summaries. To exclude results, use the exclude()
function.
Exclusion Functions
Several exclusion functions are built into PKNCA. The built-in functions will exclude all results that either apply to the current value or are dependents of the current value (parameters that depend on it). For example, depends on , and excluding based on span ratio will exclude all parameters that depend on , including .
To see the built-in functions, type ?exclude_nca and
?exclude_nca_by_param at the R command line and review
those help pages. The built-in rules exclude based on a low span ratio
(exclude_nca_span.ratio()), a high percent AUC extrapolated
(exclude_nca_max.aucinf.pext()), too few measured
concentrations for AUC calculation
(exclude_nca_count_conc_measured()), a low half-life
r-squared or adjusted r-squared
(exclude_nca_min.hl.r.squared() and
exclude_nca_min.hl.adj.r.squared()), an implausibly early
(exclude_nca_tmax_early() and
exclude_nca_tmax_0()), and samples far from the usual
times of the group (exclude_nca_tmax_coverage(), described
below). They are built on the more general
exclude_nca_by_param(), which excludes results when a
single parameter is below a minimum threshold and/or above a maximum
threshold, and which can also be used directly for any parameter. To use
them, provide the function to the FUN argument of
exclude() as illustrated below. When an exclusion function
returns its own reason text (as the built-in functions do), that text is
used as the reason for exclusion, overriding the reason
argument to exclude().
results_excl_span <- exclude(results_obj, FUN=exclude_nca_span.ratio())
# Without any exclusions applied, the 'exclude' column is all NA.
as.data.frame(results_obj) %>%
filter(Subject == 1)## # A tibble: 20 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf auclast 147. Imputation: start_p… NA
## 2 1 0 Inf cmax 10.5 Imputation: start_p… NA
## 3 1 0 Inf tmax 1.12 Imputation: start_p… NA
## 4 1 0 Inf tlast 24.4 Imputation: start_p… NA
## 5 1 0 Inf clast.obs 3.28 Imputation: start_p… NA
## 6 1 0 Inf tlag 0 Imputation: start_p… NA
## 7 1 0 Inf count_conc 11 Imputation: start_p… NA
## 8 1 0 Inf lambda.z 0.0485 Imputation: start_p… NA
## 9 1 0 Inf r.squared 1.000 Imputation: start_p… NA
## 10 1 0 Inf adj.r.squared 1.000 Imputation: start_p… NA
## 11 1 0 Inf lambda.z.corrxy -1.000 Imputation: start_p… NA
## 12 1 0 Inf lambda.z.time.first 9.05 Imputation: start_p… NA
## 13 1 0 Inf lambda.z.time.last 24.4 Imputation: start_p… NA
## 14 1 0 Inf lambda.z.n.points 3 Imputation: start_p… NA
## 15 1 0 Inf clast.pred 3.28 Imputation: start_p… NA
## 16 1 0 Inf half.life 14.3 Imputation: start_p… NA
## 17 1 0 Inf span.ratio 1.07 Imputation: start_p… NA
## 18 1 0 Inf aucinf.obs 215. Imputation: start_p… NA
## 19 1 0 Inf aucpext.obs 31.5 Imputation: start_p… NA
## 20 1 0 Inf cl.obs 0.0187 Imputation: start_p… NA
# With exclusions applied, the 'exclude' column has the reason for exclusion.
as.data.frame(results_excl_span) %>%
filter(Subject == 1)## # A tibble: 20 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf auclast 147. Imputation: start_p… NA
## 2 1 0 Inf cmax 10.5 Imputation: start_p… NA
## 3 1 0 Inf tmax 1.12 Imputation: start_p… NA
## 4 1 0 Inf tlast 24.4 Imputation: start_p… NA
## 5 1 0 Inf clast.obs 3.28 Imputation: start_p… NA
## 6 1 0 Inf tlag 0 Imputation: start_p… NA
## 7 1 0 Inf count_conc 11 Imputation: start_p… NA
## 8 1 0 Inf lambda.z 0.0485 Imputation: start_p… span.r…
## 9 1 0 Inf r.squared 1.000 Imputation: start_p… span.r…
## 10 1 0 Inf adj.r.squared 1.000 Imputation: start_p… span.r…
## 11 1 0 Inf lambda.z.corrxy -1.000 Imputation: start_p… span.r…
## 12 1 0 Inf lambda.z.time.first 9.05 Imputation: start_p… span.r…
## 13 1 0 Inf lambda.z.time.last 24.4 Imputation: start_p… span.r…
## 14 1 0 Inf lambda.z.n.points 3 Imputation: start_p… span.r…
## 15 1 0 Inf clast.pred 3.28 Imputation: start_p… span.r…
## 16 1 0 Inf half.life 14.3 Imputation: start_p… span.r…
## 17 1 0 Inf span.ratio 1.07 Imputation: start_p… span.r…
## 18 1 0 Inf aucinf.obs 215. Imputation: start_p… span.r…
## 19 1 0 Inf aucpext.obs 31.5 Imputation: start_p… span.r…
## 20 1 0 Inf cl.obs 0.0187 Imputation: start_p… span.r…
Missing Samples and Coverage
A subject who missed the samples around the peak can have a
and
that describe some other part of the profile. Two functions find those
subjects, and both work best with nominal times (the
time.nominal argument of PKNCAconc()).
pknca_missing_samples() lists, for each subject, the
nominal times of its group’s sampling schedule that have no usable
concentration: the subject has no row at that time, the concentration is
NA, or the row is excluded. The schedule of a group is
every nominal time that any subject of the group has a row for, so
recording a missed sample as a row with an NA concentration
keeps that time in the schedule.
exclude_nca_tmax_coverage() is an exclusion rule that
flags subjects whose samples miss the usual
times, and excludes only beyond the outer fences. Within each summary
group, it finds the first and third quartiles of the subjects’
values (with stats::quantile() type 7, its default) and
extends them by 1.5 times the interquartile range for the inner fences
and by 3 times it for the outer fences (Tukey’s fences; the multiples
are the k_warn and k_exclude arguments). A
subject with no sample within the outer fences is excluded. A subject
with a sample within the outer fences but none within the inner fences
gets a warning that it may be a data issue, and is not excluded. A
subject with a sample within the inner fences that is missing other
nominal times within them gets a message that
and
may be unreliable. A predose sample counts only after an intravascular
bolus. Groups with fewer than four subjects are not checked. See
?exclude_nca for the details.
The example below adds nominal times to the theophylline data and removes some samples: subject 2 loses every sample from 0.25 to 7 hours, and subject 3 loses its 1-hour concentration. Subject 2 has no sample left within the inner fences (up to 7.25 hours), but its 9-hour sample is within the outer fences (up to 11 hours), so it is flagged with a warning and not excluded. Subjects 3 and 10 (whose 0.5-hour sample was taken nearer to 1 hour) have samples within the inner fences, but each is missing one nominal time within them, so each gets a message.
nominal_times <- c(0, 0.25, 0.5, 1, 2, 3.5, 5, 7, 9, 12, 24)
d_conc_nominal <- d_conc
d_conc_nominal$Time_nominal <-
sapply(d_conc_nominal$Time, function(x) nominal_times[which.min(abs(nominal_times - x))])
d_conc_nominal <-
d_conc_nominal %>%
filter(!(Subject == 2 & Time_nominal > 0 & Time_nominal <= 7)) %>%
mutate(conc = ifelse(Subject == 3 & Time_nominal == 1, NA, conc))
conc_obj_nominal <- PKNCAconc(d_conc_nominal, conc~Time|Subject, time.nominal = "Time_nominal")
pknca_missing_samples(conc_obj_nominal)## Subject Time_nominal reason
## 1 2 0.25 no row
## 2 2 0.50 no row
## 3 2 1.00 no row
## 4 2 2.00 no row
## 5 2 3.50 no row
## 6 2 5.00 no row
## 7 2 7.00 no row
## 8 3 1.00 NA concentration
## 9 10 0.50 no row
## Warning: Too few points for half-life calculation (min.hl.points=3 with only 2
## points)
results_excl_tmax <- exclude(results_obj_nominal, FUN = exclude_nca_tmax_coverage())## Warning: Possible data issue for start=0, end=Inf, Subject=2: no sample in the
## inner Tmax range of the group (nominal time 0 to 7.25 after the interval start,
## nearest sample at 9); not excluded, since a sample is in the outer range
## Cmax and Tmax may be unreliable for start=0, end=Inf, Subject=3: no usable sample at nominal time 1, within the inner Tmax range of the group (nominal time 0 to 7.25 after the interval start)
## Cmax and Tmax may be unreliable for start=0, end=Inf, Subject=10: no usable sample at nominal time 0.5, within the inner Tmax range of the group (nominal time 0 to 7.25 after the interval start)
as.data.frame(results_excl_tmax) %>%
filter(Subject %in% 1:2, PPTESTCD %in% c("cmax", "tmax", "auclast")) %>%
select(Subject, start, end, PPTESTCD, PPORRES, exclude)## # A tibble: 6 × 6
## Subject start end PPTESTCD PPORRES exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr>
## 1 1 0 Inf auclast 147. NA
## 2 1 0 Inf cmax 10.5 NA
## 3 1 0 Inf tmax 1.12 NA
## 4 2 0 Inf auclast 53.2 NA
## 5 2 0 Inf cmax 4.55 NA
## 6 2 0 Inf tmax 9 NA
You may also write your own exclusion function. The exclusion
functions built-into PKNCA are a bit more complex than required because
they handle options and manage general functionality that may not apply
to a user-specific need. To write your own exclusion function, it should
follow the description of how to write your own exclusion function as
described in the details section of ?exclude.
Excluding Specific Results
Excluding specific results has the benefit that full control is provided. But, excluding specific points allows for errors to also enter the analysis because parameters that depend on the excluded parameter will not be excluded.
mask_exclude_cmax <-
results_obj %>%
as.data.frame() %>%
dplyr::mutate(
mask_exclude=Subject == 1 & PPTESTCD == "cmax"
) %>%
"[["("mask_exclude")
results_excl_specific <-
exclude(
results_obj,
mask=mask_exclude_cmax,
reason="Cmax was actually above the ULOQ"
)
# Without any exclusions applied, the 'exclude' column is all NA.
results_obj %>%
as.data.frame() %>%
filter(Subject == 1)## # A tibble: 20 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf auclast 147. Imputation: start_p… NA
## 2 1 0 Inf cmax 10.5 Imputation: start_p… NA
## 3 1 0 Inf tmax 1.12 Imputation: start_p… NA
## 4 1 0 Inf tlast 24.4 Imputation: start_p… NA
## 5 1 0 Inf clast.obs 3.28 Imputation: start_p… NA
## 6 1 0 Inf tlag 0 Imputation: start_p… NA
## 7 1 0 Inf count_conc 11 Imputation: start_p… NA
## 8 1 0 Inf lambda.z 0.0485 Imputation: start_p… NA
## 9 1 0 Inf r.squared 1.000 Imputation: start_p… NA
## 10 1 0 Inf adj.r.squared 1.000 Imputation: start_p… NA
## 11 1 0 Inf lambda.z.corrxy -1.000 Imputation: start_p… NA
## 12 1 0 Inf lambda.z.time.first 9.05 Imputation: start_p… NA
## 13 1 0 Inf lambda.z.time.last 24.4 Imputation: start_p… NA
## 14 1 0 Inf lambda.z.n.points 3 Imputation: start_p… NA
## 15 1 0 Inf clast.pred 3.28 Imputation: start_p… NA
## 16 1 0 Inf half.life 14.3 Imputation: start_p… NA
## 17 1 0 Inf span.ratio 1.07 Imputation: start_p… NA
## 18 1 0 Inf aucinf.obs 215. Imputation: start_p… NA
## 19 1 0 Inf aucpext.obs 31.5 Imputation: start_p… NA
## 20 1 0 Inf cl.obs 0.0187 Imputation: start_p… NA
# With exclusions applied, the 'exclude' column has the reason for exclusion.
results_excl_specific %>%
as.data.frame() %>%
filter(Subject == 1)## # A tibble: 20 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf auclast 147. Imputation: start_p… NA
## 2 1 0 Inf cmax 10.5 Imputation: start_p… Cmax w…
## 3 1 0 Inf tmax 1.12 Imputation: start_p… NA
## 4 1 0 Inf tlast 24.4 Imputation: start_p… NA
## 5 1 0 Inf clast.obs 3.28 Imputation: start_p… NA
## 6 1 0 Inf tlag 0 Imputation: start_p… NA
## 7 1 0 Inf count_conc 11 Imputation: start_p… NA
## 8 1 0 Inf lambda.z 0.0485 Imputation: start_p… NA
## 9 1 0 Inf r.squared 1.000 Imputation: start_p… NA
## 10 1 0 Inf adj.r.squared 1.000 Imputation: start_p… NA
## 11 1 0 Inf lambda.z.corrxy -1.000 Imputation: start_p… NA
## 12 1 0 Inf lambda.z.time.first 9.05 Imputation: start_p… NA
## 13 1 0 Inf lambda.z.time.last 24.4 Imputation: start_p… NA
## 14 1 0 Inf lambda.z.n.points 3 Imputation: start_p… NA
## 15 1 0 Inf clast.pred 3.28 Imputation: start_p… NA
## 16 1 0 Inf half.life 14.3 Imputation: start_p… NA
## 17 1 0 Inf span.ratio 1.07 Imputation: start_p… NA
## 18 1 0 Inf aucinf.obs 215. Imputation: start_p… NA
## 19 1 0 Inf aucpext.obs 31.5 Imputation: start_p… NA
## 20 1 0 Inf cl.obs 0.0187 Imputation: start_p… NA
Multiple Exclusions
More than one exclusion can be applied sequentially to results as in the example below.
mask_exclude_lz <-
results_obj %>%
as.data.frame() %>%
dplyr::mutate(
mask_exclude=Subject == 1 & PPTESTCD == "lambda.z"
) %>%
"[["("mask_exclude")
# Starting from the exclusion example above where short span ratios were
# excluded, exclude Cmax for Subject 1, too.
results_excl_multi <-
exclude(
results_excl_span,
mask=mask_exclude_cmax,
reason="Cmax was actually above the ULOQ"
)
results_excl_multi <-
exclude(
results_excl_multi,
mask=mask_exclude_lz,
reason="Issue with lambda.z fit"
)
# With exclusions applied, the 'exclude' column has the reason for exclusion.
# More than one reason may appear if more than one exclusion is applied.
results_excl_multi %>%
as.data.frame() %>%
filter(Subject == 1)## # A tibble: 20 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf auclast 147. Imputation: start_p… NA
## 2 1 0 Inf cmax 10.5 Imputation: start_p… Cmax w…
## 3 1 0 Inf tmax 1.12 Imputation: start_p… NA
## 4 1 0 Inf tlast 24.4 Imputation: start_p… NA
## 5 1 0 Inf clast.obs 3.28 Imputation: start_p… NA
## 6 1 0 Inf tlag 0 Imputation: start_p… NA
## 7 1 0 Inf count_conc 11 Imputation: start_p… NA
## 8 1 0 Inf lambda.z 0.0485 Imputation: start_p… span.r…
## 9 1 0 Inf r.squared 1.000 Imputation: start_p… span.r…
## 10 1 0 Inf adj.r.squared 1.000 Imputation: start_p… span.r…
## 11 1 0 Inf lambda.z.corrxy -1.000 Imputation: start_p… span.r…
## 12 1 0 Inf lambda.z.time.first 9.05 Imputation: start_p… span.r…
## 13 1 0 Inf lambda.z.time.last 24.4 Imputation: start_p… span.r…
## 14 1 0 Inf lambda.z.n.points 3 Imputation: start_p… span.r…
## 15 1 0 Inf clast.pred 3.28 Imputation: start_p… span.r…
## 16 1 0 Inf half.life 14.3 Imputation: start_p… span.r…
## 17 1 0 Inf span.ratio 1.07 Imputation: start_p… span.r…
## 18 1 0 Inf aucinf.obs 215. Imputation: start_p… span.r…
## 19 1 0 Inf aucpext.obs 31.5 Imputation: start_p… span.r…
## 20 1 0 Inf cl.obs 0.0187 Imputation: start_p… span.r…
Normalizing Results
PKNCA provides functions to normalize calculated parameters by columns in your data or by using normalization tables.
Example: Normalize by a column in the concentration data
The function normalize_by_col() allows you to normalize
parameters by any column present in the concentration data of your
PKNCAresults object. You can also specify the unit as another column in
the concentration data or as a constant value.
Suppose your concentration data includes a column for body weight, and you want to normalize Cmax by each subject’s weight:
# Add a weight column to the concentration data
d_conc2 <- d_conc
d_conc2$weight <- unname(setNames(60:71, 1:12)[d_conc2$Subject])
d_conc2$weight_unit <- "kg"
# Recreate the PKNCA objects with the new column
conc_obj2 <- PKNCAconc(
d_conc2,
conc~Time|Subject
)
dose_obj2 <- PKNCAdose(
d_dose,
Dose~Time|Subject
)
data_obj2 <- PKNCAdata(conc_obj2, dose_obj2)
results_obj2 <- pk.nca(data_obj2)
# Normalize Cmax by the 'weight' column
results_norm_by_col <- normalize_by_col(
results_obj2,
col = "weight",
unit = "weight_unit",
parameters = "cmax",
suffix = ".wn"
)
# Show the normalized results appended
as.data.frame(results_norm_by_col) %>% filter(PPTESTCD == "cmax.wn")## # A tibble: 12 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf cmax.wn 0.175 Imputation: start_predose_conc0 NA
## 2 2 0 Inf cmax.wn 0.137 Imputation: start_predose_conc0 NA
## 3 3 0 Inf cmax.wn 0.132 Imputation: start_predose_conc0 NA
## 4 4 0 Inf cmax.wn 0.137 Imputation: start_predose_conc0 NA
## 5 5 0 Inf cmax.wn 0.178 Imputation: start_predose_conc0 NA
## 6 6 0 Inf cmax.wn 0.0991 Imputation: start_predose_conc0 NA
## 7 7 0 Inf cmax.wn 0.107 Imputation: start_predose_conc0 NA
## 8 8 0 Inf cmax.wn 0.113 Imputation: start_predose_conc0 NA
## 9 9 0 Inf cmax.wn 0.133 Imputation: start_predose_conc0 NA
## 10 10 0 Inf cmax.wn 0.148 Imputation: start_predose_conc0 NA
## 11 11 0 Inf cmax.wn 0.114 Imputation: start_predose_conc0 NA
## 12 12 0 Inf cmax.wn 0.137 Imputation: start_predose_conc0 NA
Doing custom normalizations
If your data does not have the normalization column explicitly, you
can perform the same normalization using the normalize()
function by providing a normalization table. Below, we use the same
subject weights as above to normalize Cmax, but without adding the
weight column to the concentration data:
# Use the same subject_weights as above
norm_table <- data.frame(Subject = unique(d_conc$Subject), normalization = 60:71, unit = "kg")
results_norm_custom <- normalize(
results_obj,
norm_table = norm_table,
parameters = "cmax",
suffix = ".wn"
)
as.data.frame(results_norm_custom) %>% filter(PPTESTCD == "cmax.wn")## # A tibble: 12 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf cmax.wn 0.175 Imputation: start_predose_conc0 NA
## 2 2 0 Inf cmax.wn 0.137 Imputation: start_predose_conc0 NA
## 3 3 0 Inf cmax.wn 0.132 Imputation: start_predose_conc0 NA
## 4 4 0 Inf cmax.wn 0.137 Imputation: start_predose_conc0 NA
## 5 5 0 Inf cmax.wn 0.178 Imputation: start_predose_conc0 NA
## 6 6 0 Inf cmax.wn 0.0991 Imputation: start_predose_conc0 NA
## 7 7 0 Inf cmax.wn 0.107 Imputation: start_predose_conc0 NA
## 8 8 0 Inf cmax.wn 0.113 Imputation: start_predose_conc0 NA
## 9 9 0 Inf cmax.wn 0.133 Imputation: start_predose_conc0 NA
## 10 10 0 Inf cmax.wn 0.148 Imputation: start_predose_conc0 NA
## 11 11 0 Inf cmax.wn 0.114 Imputation: start_predose_conc0 NA
## 12 12 0 Inf cmax.wn 0.137 Imputation: start_predose_conc0 NA
Extracting Results
Summary Results
Summary results are obtained using the aptly named
summary() function. It will output a
summary_PKNCAresults object that is simply a data.frame
with an attribute of caption. The summary is generated by
evaluating summary statistics on each requested parameter. Which summary
statistics are calculated for each parameter are set with
PKNCA.set.summary(), and they are described in the caption.
When a parameter is not requested for a given interval, it is
illustrated with a period (.), by default (customizable
with the not_requested argument to summary()).
When a parameter is requested but cannot be calculated, it is
illustrated with NC, by default (customizable with the
not_calculated argument to summary()), and
that abbreviation is described in the caption. When a parameter is
required to calculate another parameter, but it is not specifically
requested, it will not be shown in the summary.
The summary will have one column for each grouping variable other than the subject grouping variable; one column each for the start and end time; and one column per parameter calculated.
summary(results_obj)## start end N auclast cmax tmax tlag
## 0 Inf 12 98.7 [22.5] 8.65 [17.0] 1.14 [0.630, 3.55] 0.000 [0.000, 0.000]
## count_conc half.life aucinf.obs aucpext.obs cl.obs
## 11.0 [11.0, 11.0] 8.18 [2.12] 115 [28.4] 13.8 [6.34] 0.0398 [29.4]
##
## Caption: auclast, cmax, aucinf.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
When values are excluded as described above, the excluded values are not included in the summary (note that half.life and aucinf.obs differ).
summary(results_excl_span)## start end N auclast cmax tmax tlag
## 0 Inf 12 98.7 [22.5] 8.65 [17.0] 1.14 [0.630, 3.55] 0.000 [0.000, 0.000]
## count_conc half.life aucinf.obs aucpext.obs
## 11.0 [11.0, 11.0] 7.36 [0.742], n=9 105 [16.4], n=9 11.3 [2.28], n=9
## cl.obs
## 0.0453 [11.2], n=9
##
## Caption: auclast, cmax, aucinf.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; n: number of measurements included in summary
Listing of Results
A listing of all calculated values is available using
as.data.frame().
as.data.frame(results_obj) %>%
head(20)## # A tibble: 20 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf auclast 147. Imputation: start_p… NA
## 2 1 0 Inf cmax 10.5 Imputation: start_p… NA
## 3 1 0 Inf tmax 1.12 Imputation: start_p… NA
## 4 1 0 Inf tlast 24.4 Imputation: start_p… NA
## 5 1 0 Inf clast.obs 3.28 Imputation: start_p… NA
## 6 1 0 Inf tlag 0 Imputation: start_p… NA
## 7 1 0 Inf count_conc 11 Imputation: start_p… NA
## 8 1 0 Inf lambda.z 0.0485 Imputation: start_p… NA
## 9 1 0 Inf r.squared 1.000 Imputation: start_p… NA
## 10 1 0 Inf adj.r.squared 1.000 Imputation: start_p… NA
## 11 1 0 Inf lambda.z.corrxy -1.000 Imputation: start_p… NA
## 12 1 0 Inf lambda.z.time.first 9.05 Imputation: start_p… NA
## 13 1 0 Inf lambda.z.time.last 24.4 Imputation: start_p… NA
## 14 1 0 Inf lambda.z.n.points 3 Imputation: start_p… NA
## 15 1 0 Inf clast.pred 3.28 Imputation: start_p… NA
## 16 1 0 Inf half.life 14.3 Imputation: start_p… NA
## 17 1 0 Inf span.ratio 1.07 Imputation: start_p… NA
## 18 1 0 Inf aucinf.obs 215. Imputation: start_p… NA
## 19 1 0 Inf aucpext.obs 31.5 Imputation: start_p… NA
## 20 1 0 Inf cl.obs 0.0187 Imputation: start_p… NA
Excluded values remain in the listing.
as.data.frame(results_excl_span) %>%
head(20)## # A tibble: 20 × 7
## Subject start end PPTESTCD PPORRES PPANMETH exclude
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 1 0 Inf auclast 147. Imputation: start_p… NA
## 2 1 0 Inf cmax 10.5 Imputation: start_p… NA
## 3 1 0 Inf tmax 1.12 Imputation: start_p… NA
## 4 1 0 Inf tlast 24.4 Imputation: start_p… NA
## 5 1 0 Inf clast.obs 3.28 Imputation: start_p… NA
## 6 1 0 Inf tlag 0 Imputation: start_p… NA
## 7 1 0 Inf count_conc 11 Imputation: start_p… NA
## 8 1 0 Inf lambda.z 0.0485 Imputation: start_p… span.r…
## 9 1 0 Inf r.squared 1.000 Imputation: start_p… span.r…
## 10 1 0 Inf adj.r.squared 1.000 Imputation: start_p… span.r…
## 11 1 0 Inf lambda.z.corrxy -1.000 Imputation: start_p… span.r…
## 12 1 0 Inf lambda.z.time.first 9.05 Imputation: start_p… span.r…
## 13 1 0 Inf lambda.z.time.last 24.4 Imputation: start_p… span.r…
## 14 1 0 Inf lambda.z.n.points 3 Imputation: start_p… span.r…
## 15 1 0 Inf clast.pred 3.28 Imputation: start_p… span.r…
## 16 1 0 Inf half.life 14.3 Imputation: start_p… span.r…
## 17 1 0 Inf span.ratio 1.07 Imputation: start_p… span.r…
## 18 1 0 Inf aucinf.obs 215. Imputation: start_p… span.r…
## 19 1 0 Inf aucpext.obs 31.5 Imputation: start_p… span.r…
## 20 1 0 Inf cl.obs 0.0187 Imputation: start_p… span.r…
Concentrations Used for Half-Life Estimation
To find which concentration measurements were used for the half-life
()
estimation, use get_halflife_points(). It returns a logical
vector with one value per row of the concentration data:
TRUE if the point was used in the half-life fit,
FALSE if it was not used but a half-life was calculated for
the interval, and NA if no half-life was calculated for the
interval (or if the row is excluded from all calculations). It accepts
either a PKNCAresults or a PKNCAdata object (with a PKNCAdata object,
the half-life is calculated first), and the intervals do not need to
start at time 0.
d_conc_hl <- d_conc
d_conc_hl$hl_used <- get_halflife_points(results_obj)
# The points used for the half-life fit are the later time points
d_conc_hl %>%
filter(Subject == 1)## Subject Wt Dose Time conc hl_used
## 1 1 79.6 4.02 0.00 0.74 FALSE
## 2 1 79.6 4.02 0.25 2.84 FALSE
## 3 1 79.6 4.02 0.57 6.57 FALSE
## 4 1 79.6 4.02 1.12 10.50 FALSE
## 5 1 79.6 4.02 2.02 9.66 FALSE
## 6 1 79.6 4.02 3.82 8.58 FALSE
## 7 1 79.6 4.02 5.10 8.36 FALSE
## 8 1 79.6 4.02 7.03 7.47 FALSE
## 9 1 79.6 4.02 9.05 6.89 TRUE
## 10 1 79.6 4.02 12.12 5.94 TRUE
## 11 1 79.6 4.02 24.37 3.28 TRUE
The Half-Life Fit
get_halflife_fit() gives the log-linear fit itself, one
row per group and interval, as the slope and intercept of
log(conc) = intercept + slope*time. The slope is
.
get_halflife_fit(results_obj)## Subject start end intercept slope time_first time_last
## 1 1 0 Inf 2.368785 -0.04845700 9.05 24.37
## 2 2 0 Inf 2.411237 -0.10408644 7.03 24.30
## 3 3 0 Inf 2.529712 -0.10244431 9.00 24.17
## 4 4 0 Inf 2.592755 -0.09928702 9.02 24.65
## 5 5 0 Inf 2.551092 -0.08661888 7.02 24.35
## 6 6 0 Inf 2.033404 -0.08779574 2.03 23.85
## 7 7 0 Inf 2.288550 -0.08833650 6.98 24.22
## 8 8 0 Inf 2.170403 -0.08145054 3.53 24.12
## 9 9 0 Inf 2.124648 -0.08245863 8.80 24.43
## 10 10 0 Inf 2.657705 -0.07495982 9.38 23.70
## 11 11 0 Inf 2.147594 -0.09545856 9.03 24.08
## 12 12 0 Inf 2.824493 -0.11025949 9.03 24.15
Times in a PKNCAresults object are relative to the start of the
interval, but time_first, time_last, and the
time scale of intercept are all on the same scale as the
times in the concentration data. The fitted line can therefore be drawn
with the observed concentrations without shifting anything.
intercept and slope are NA when
the half-life could not be calculated or was excluded.
Concentrations Along the Half-Life Fit
get_halflife_curve() gives concentrations along that
line. As with stats::approx(), give either n
for equally-spaced times or tout for specific times.
Concentrations are returned as concentrations, not
log-concentrations.
With n, the times span the concentrations used for the
fit:
get_halflife_curve(results_obj, n = 5) %>%
filter(Subject == 1)## Subject start end time conc
## 1 1 0 Inf 9.05 6.891228
## 2 1 0 Inf 12.88 5.723949
## 3 1 0 Inf 16.71 4.754391
## 4 1 0 Inf 20.54 3.949063
## 5 1 0 Inf 24.37 3.280146
With tout, any times may be requested. Extrapolation
after the last concentration used for the fit is done by default, and
extrapolation before the first is not, so early times give
NA:
get_halflife_curve(results_obj, tout = c(0, 12, 48)) %>%
filter(Subject == 1)## Subject start end time conc
## 1 1 0 Inf 0 NA
## 2 1 0 Inf 12 5.973310
## 3 1 0 Inf 48 1.043781
Both defaults can be changed with the
extrapolate_earlier and extrapolate_later
arguments:
get_halflife_curve(
results_obj,
tout = c(0, 12, 48),
extrapolate_earlier = TRUE,
extrapolate_later = FALSE
) %>%
filter(Subject == 1)## Subject start end time conc
## 1 1 0 Inf 0 10.68440
## 2 1 0 Inf 12 5.97331
## 3 1 0 Inf 48 NA