Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c2f8e17
feat: include ppanmeth column in pk.nca output
Gero1999 Aug 30, 2025
32b19a3
specify arg for ppanmeth and fix paste issue
Gero1999 Aug 30, 2025
e17ab38
add tests for PPANMETH in pk.nca output
Gero1999 Aug 30, 2025
f75865d
update pk.nca.Rd docs
Gero1999 Aug 30, 2025
0e7de7a
news: add ppanmeth feat
Gero1999 Aug 30, 2025
2b4c1b5
refactor a bit tests
Gero1999 Aug 30, 2025
ec03c2c
Merge remote-tracking branch 'origin/main' into add-ppanmeth
Gero1999 Sep 12, 2025
7ea493d
modify: rm arg option from pk.nca and news
Gero1999 Sep 12, 2025
6fb8505
test: rm ppanmeth arg
Gero1999 Sep 12, 2025
91d4975
fix: disconsider PPANMETH for wide results
Gero1999 Sep 13, 2025
e632ed7
test: add PPANMETH col when relevant
Gero1999 Sep 13, 2025
e7a1145
docs: rm add_ppanmeth arg
Gero1999 Sep 13, 2025
9bf05d0
fix: typpo in NEWS.md
Gero1999 Oct 19, 2025
b5ce26b
Merge branch 'main' into add-ppanmeth
Gero1999 Nov 13, 2025
3be8500
rm method definition for half.life & AUC from pk.calc.all.R
Gero1999 Nov 24, 2025
6a0e7d3
add method as attr in auc.R, aucint.R and half.life.R
Gero1999 Nov 24, 2025
eae9721
modify tests: expect_equal calls to ignore attributes & add attr meth…
Gero1999 Nov 24, 2025
d3095e2
fix: remove attr method from pk.nca result (PPANMETH already has this…
Gero1999 Nov 24, 2025
4dd25c3
add method attr to auc sparse calculations
Gero1999 Nov 24, 2025
8fb9d99
namespace na.omit
Gero1999 Nov 24, 2025
c6ab60a
refactor attr method assignment
Gero1999 Nov 24, 2025
1c45fe3
test: ignore_attr when relevant
Gero1999 Nov 24, 2025
d03e2eb
Merge branch 'main' into add-ppanmeth
Gero1999 Nov 24, 2025
d8f1877
merge: accept both incoming/current changes (different tests)
Gero1999 Jan 12, 2026
f48cb19
Merge: accept both changes (NEWS.md, test-pk.calc.all) remote-trackin…
Gero1999 Feb 13, 2026
521fcf9
Merge branch 'add-ppanmeth' of https://github.com/Gero1999/pknca into…
Gero1999 Feb 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ the dosing including dose amount and route.
* `pk.calc.half.life()` now returns also `lambda.z.corrxy`, the correlation between
the time and the log-concentration of the lambda z points.

* `pk.nca` output now includes a `PPANMETH` column describing the analysis methods used for each parameter regarding imputations, AUC and half.life calculations (#457)

# PKNCA 0.12.1

## Minor changes (unlikely to affect PKNCA use)
Expand Down
2 changes: 1 addition & 1 deletion R/class-PKNCAresults.R
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ as.data.frame.PKNCAresults <- function(x, ..., out_format = c('long', 'wide'), f
# Since we moved the results into PPTESTCD and PPORRES regardless of what
# they really are in the source data, remove the extra units and unit
# conversion columns to allow spread to work.
ret <- ret[, setdiff(names(ret), c("PPSTRES", "PPSTRESU", "PPORRESU"))]
ret <- ret[, setdiff(names(ret), c("PPSTRES", "PPSTRESU", "PPORRESU", "PPANMETH"))]
ret <- tidyr::spread(ret, key="PPTESTCD", value="PPORRES")
}
ret
Expand Down
41 changes: 35 additions & 6 deletions R/pk.calc.all.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
#' the interval. For example, if an interval starts at 168 hours, ends at 192
#' hours, and and the maximum concentration is at 169 hours, `tmax=169-168=1`.
#'
#' @param data A PKNCAdata object
#' @param verbose Indicate, by `message()`, the current state of calculation.
#' @returns A `PKNCAresults` object.
#' @seealso [PKNCAdata()], [PKNCA.options()], [summary.PKNCAresults()],
#' [as.data.frame.PKNCAresults()], [exclude()]
#' @export
##' @param data A PKNCAdata object
##' @param verbose Indicate, by `message()`, the current state of calculation.
##' @returns A `PKNCAresults` object.
##' @seealso [PKNCAdata()], [PKNCA.options()], [summary.PKNCAresults()],
##' [as.data.frame.PKNCAresults()], [exclude()]
##' @export
pk.nca <- function(data, verbose=FALSE) {
assert_PKNCAdata(data)
results <- data.frame()
Expand Down Expand Up @@ -363,6 +363,7 @@ pk.nca.interval <- function(conc, time, volume, duration.conc,
if (nrow(interval) != 1) {
stop("Please report a bug. Interval must be a one-row data.frame")
}

if (!all(is.na(impute_method))) {
impute_funs <- PKNCA_impute_fun_list(impute_method)
stopifnot(length(impute_funs) == 1)
Expand All @@ -378,6 +379,11 @@ pk.nca.interval <- function(conc, time, volume, duration.conc,
}
conc <- impute_data$conc
time <- impute_data$time
tmp_imp_method <- c(
paste0("Imputation: ", paste(na.omit(impute_method), collapse = ", "))
)
} else {
tmp_imp_method <- c()
}
# Prepare the return value using SDTM names
ret <- data.frame(PPTESTCD=NA, PPORRES=NA)[-1,]
Expand All @@ -399,6 +405,7 @@ pk.nca.interval <- function(conc, time, volume, duration.conc,
}
# Do the calculations
for (n in names(all_intervals)) {
tmp_method <- c(tmp_imp_method)
request_to_calculate <- as.logical(interval[[n]])
has_calculation_function <- !is.na(all_intervals[[n]]$FUN)
is_correct_sparse_dense <- all_intervals[[n]]$sparse == sparse
Expand Down Expand Up @@ -485,6 +492,7 @@ pk.nca.interval <- function(conc, time, volume, duration.conc,
}
}
}

# Apply manual inclusion and exclusion
if (n %in% "half.life") {
if (!is.null(include_half.life) && !all(is.na(include_half.life))) {
Expand All @@ -498,6 +506,26 @@ pk.nca.interval <- function(conc, time, volume, duration.conc,
call_args$time <- call_args$time[!exclude_tf]
}
}
# For half-life related parameters, indicate if there was any manual inclusion / exclusion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather that the method be applied within the calculation function rather than at the intervals level. That way, if we add more PPANMETH values in the future (e.g. first vs last cmax) it will apply directly.

Perhaps the best/easiest way is to make it work the same way that exclusions work now with an attribute on the returned object.

I'd also be open to having a ppanmeth = FALSE flag set for functions which would have them return a data.frame with PPANMETH, if TRUE. (Though I generally prefer consistent return value classes rather than return value classes that depend on input-- for ease of general use.)

Copy link
Contributor Author

@Gero1999 Gero1999 Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this logical path seems better. I have some difficulties imaging these implementations. Lmk if you can help me, otherwise I will just try to address them naively:

attributes

  1. The regular user won't check attr and will see output differences between pk.calc (attr) & pk.nca (col) that cannot be replicated
  2. Most of the expect_equal tests associated with pk.nca results and derived obj don't ignore attributes.

ppanmeth = FALSE

  1. Imputations should be indicated in PPANMETH, that also helps distinguishing the results from same intervals with different imputations. I guess it should be once per interval. If I follow the attr strategy I can see using vectors, but with the pk.calc(ppanmeth = FALSE) strategy then, how do I elude repetition?

if (n %in% get.parameter.deps("half.life")) {
any_inclusion <- !is.null(include_half.life) && !all(is.na(include_half.life))
any_exclusion <- !is.null(exclude_half.life) && !all(is.na(exclude_half.life))
tmp_method <- c(
tmp_method,
paste0(
"Lambda Z: ",
{if (any_inclusion) "Manual selection" else if (any_exclusion) "Manual exclusion" else "Default"}
)
)
}
# For AUC parameters, indicate the calculation method
auc_parameters <- grep("auc", names(get.interval.cols()), value = TRUE)
if (n %in% auc_parameters) {
tmp_method <- c(
tmp_method,
paste0("AUC: ", options$auc.method)
)
}
# Do the calculation
tmp_result <- do.call(all_intervals[[n]]$FUN, call_args)
# The handling of the exclude column is documented in the
Expand Down Expand Up @@ -548,6 +576,7 @@ pk.nca.interval <- function(conc, time, volume, duration.conc,
data.frame(
PPTESTCD=tmp_testcd,
PPORRES=tmp_result,
PPANMETH=paste(tmp_method, collapse=". "),
exclude=exclude_reason,
stringsAsFactors=FALSE
)
Expand Down
Loading