Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Slope Selector Plots Incorrect #177

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e4dd97f
feat: create duplicates for slope plots
Jan 22, 2025
478f4a2
merge with multiple analytes
Jan 24, 2025
50881bd
refactor: make slopes_groups() variable instead of hardcoding slopes …
Jan 28, 2025
f92ffd7
merge and resolve conflicts with main
Jan 28, 2025
0b3d38e
fix: update create duplicates
Jan 28, 2025
928f7ef
refactor: remove unique values from slopes_groups
Jan 28, 2025
13e715d
refactor: remove slope_groups from lambda plot
Jan 29, 2025
251498b
refactor to reduce cyclomatic complexity
Jan 29, 2025
4ac9431
test: add testing for create_duplicates
Jan 30, 2025
f3f61d0
include testing file
Jan 30, 2025
39bfd9c
fix and refactor: plotly slope selection
Jan 31, 2025
02da5fd
update slopes table sizing
Jan 31, 2025
d12a5ec
lint, spellcheck and check updates
Jan 31, 2025
b0ac3e2
bug fix: plotly click updated
Jan 31, 2025
51ae458
lint
Jan 31, 2025
cc71fec
refactor: slopes functions
Jan 31, 2025
eadaac6
fix: remove . from functions
Jan 31, 2025
4e1c887
refactor: remove filter(across()) and make slopes_groups easier to read
Feb 3, 2025
f6ad44a
Merge branch 'main' into bug/slope-selector-incorrect
js3110 Feb 4, 2025
5d49818
lint
Feb 4, 2025
718e925
PPSTRES instead of PPORRES
Feb 4, 2025
3d7058e
update roxygen docs
Feb 4, 2025
e760ab5
üpdate slope plots styling
Feb 5, 2025
47ed412
fix: consider pknca_conc groups for multiple analyte (format_pkncadat…
Gero1999 Feb 4, 2025
3e86f64
fix: prevent standardization on time starts to remove rows in join
Gero1999 Feb 5, 2025
e79108e
fix: improve function in case DOSNO is not present
Gero1999 Feb 5, 2025
f49d33e
testing: add test with a metabolite case to format_pkncadata_intervals
Gero1999 Feb 5, 2025
adc2dc6
refactor: lintr code cleaning
Gero1999 Feb 5, 2025
27e3c71
documentation: update roxygen
Gero1999 Feb 5, 2025
bd482cf
testing & fix: consider case pknca_conc is in wrong format
Gero1999 Feb 5, 2025
766bd6a
nitpick: add requested comments
Gero1999 Feb 5, 2025
c53338c
fix: start and end time bug
Feb 5, 2025
884f6b9
update TIME var for slope plots
Feb 5, 2025
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
11 changes: 3 additions & 8 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ export(apply_filters)
export(apply_labels)
export(as_factor_preserve_label)
export(calculate_summary_stats)
export(check_slope_rule_overlap)
export(create_duplicates)
export(create_start_impute)
export(export_cdisc)
export(filter_breaks)
export(filter_slopes)
export(flexible_violinboxplot)
export(format_pkncaconc_data)
export(format_pkncadata_intervals)
Expand Down Expand Up @@ -62,14 +61,10 @@ importFrom(ggplot2,labs)
importFrom(ggplot2,scale_x_continuous)
importFrom(glue,glue)
importFrom(grid,convertUnit)
importFrom(logger,log_debug)
importFrom(logger,log_error)
importFrom(logger,log_fatal)
importFrom(logger,log_info)
importFrom(logger,log_trace)
importFrom(logger,log_warn)
importFrom(magrittr,`%>%`)
importFrom(purrr,imap)
importFrom(purrr,map)
importFrom(purrr,reduce)
importFrom(rlang,sym)
importFrom(scales,breaks_log)
importFrom(scales,label_log)
Expand Down
95 changes: 95 additions & 0 deletions R/create_duplicates.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#' Create duplicates in concentration data with Predose and Last Values for Dosing Cycles
#'
#' This function duplicates and adjusts concentration data to ensure all dosing cycles have
#' complete predose and last concentration values. It is designed for use in pharmacokinetic
#' analyses where dosing intervals and concentration values need to be aligned for each dose.
#'
#' @param conc_data A data frame containing concentration data.
#' @param groups A character vector of column names to use for grouping (e.g., c("USUBJID", "ANALYTE", "PCSPEC")).
#' @param dosno Column name for the dose number (default: "DOSNO").
#' @param arrlt Column name for time from the most recent dose (default: "ARRLT").
#' @param afrlt Column name for time from the first dose (default: "AFRLT").
#' @param nrrlt Column name for the numeric relative time (default: "NRRLT").
#' @param nfrlt Column name for the nominal relative time (default: "NFRLT").
#'
#' @return A data frame with adjusted concentration data, including:
js3110 marked this conversation as resolved.
Show resolved Hide resolved
#' - Duplicated predose values assigned to the previous dose.
#' - Duplicated last values assigned to the next dose if predose values are missing.
#' - Sorted by the grouping variables and relative time.
#'
#' @examples
#' # Example usage
#' result <- adjust_concentration_data(conc_data, groups = c("USUBJID", "ANALYTE", "PCSPEC"), dosno = "DOSNO")
#'
#' @export
create_duplicates <- function(conc_data,
Copy link
Collaborator

Choose a reason for hiding this comment

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

nitpick: Would be better if the function name told you what kind of duplicates it creates.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@m-kolomanski I'm not sure how to define that in a way that makes sense and is less than 5 words... open to suggestions !

Copy link
Collaborator

Choose a reason for hiding this comment

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

the function is working both ways right? English was never my strength, but one possibility is perhaps duplicate_predoses_and_lastdoses

groups = c("USUBJID", "ANALYTE", "PCSPEC"),
dosno = "DOSNO",
arrlt = "ARRLT",
afrlt = "AFRLT",
nrrlt = "NRRLT",
nfrlt = "NFRLT") {
# Helper to construct grouping keys
group_keys <- function(data, keys) {
data %>%
group_by(across(all_of(keys)))
}
js3110 marked this conversation as resolved.
Show resolved Hide resolved

# Step 1: Identify the dosing times (ARRLT == 0)
dose_times <- conc_data %>%
mutate(dose_time = .data[[afrlt]] - .data[[arrlt]]) %>%
select(all_of(groups), .data[[dosno]], dose_time) %>%
group_keys(c(groups, dosno)) %>%
summarize(dose_time = first(dose_time), .groups = "drop")

# Step 2: Calculate dosing intervals
dosing_intervals <- dose_times %>%
group_keys(groups) %>%
mutate(
interval_next = lead(dose_time) - dose_time,
interval_prev = dose_time - lag(dose_time),
interval_next = replace_na(interval_next, 0),
interval_prev = replace_na(interval_prev, 0),
next_dose = interval_next + dose_time
js3110 marked this conversation as resolved.
Show resolved Hide resolved
) %>%
ungroup()

# Step 3: Duplicate predose values for the previous dose
predose_duplicates <- conc_data %>%
filter(.data[[arrlt]] <= 0, .data[[dosno]] > 1) %>%
left_join(dosing_intervals, by = c(dosno, groups)) %>%
mutate(
!!dosno := .data[[dosno]] - 1,
!!arrlt := .data[[arrlt]] + interval_prev,
js3110 marked this conversation as resolved.
Show resolved Hide resolved
!!nrrlt := .data[[nfrlt]] - interval_prev
js3110 marked this conversation as resolved.
Show resolved Hide resolved
) %>%
select(-interval_next, -interval_prev)

# Step 4: Identify missing predose values for the next dose
missing_predose <- dose_times %>%
anti_join(
conc_data %>% filter(.data[[arrlt]] < 0),
by = c(groups, dosno)
)

# Step 5: Duplicate last value of the previous dose
last_values <- conc_data %>%
semi_join(missing_predose, by = c(groups, dosno)) %>%
group_keys(c(groups, dosno)) %>%
slice_tail(n = 1) %>%
ungroup() %>%
left_join(dosing_intervals, by = c(groups, dosno)) %>%
mutate(
!!dosno := .data[[dosno]] + 1,
!!arrlt := .data[[arrlt]] - interval_prev,
!!nrrlt := .data[[nrrlt]] + interval_prev
js3110 marked this conversation as resolved.
Show resolved Hide resolved
) %>%
select(-interval_next, -interval_prev)

# Step 6: Combine all data
conc_data <- conc_data %>%
bind_rows(predose_duplicates, last_values) %>%
arrange(across(all_of(c(groups, dosno, arrlt))))

return(conc_data)
}
2 changes: 1 addition & 1 deletion R/format_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ format_pkncadata_intervals <- function(pknca_dose,
arrange(!!sym(pknca_dose$columns$time)) %>%
mutate(end = lead(as.numeric(!!sym(pknca_dose$columns$time)), default = Inf)) %>%
ungroup() %>%
select(any_of(c("start", "end", unname(unlist(pknca_dose$columns$groups)), "DOSNO"))) %>%
select(any_of(c("start", "end", unname(unlist(pknca_dose$columns$groups)), "DOSNO", "ANALYTE"))) %>% #TODO: Gerardo adjust to remove hardcoding

# Create logical columns with the TRUE and as names params argument
mutate(!!!setNames(rep(TRUE, length(params)), params)) %>%
Expand Down
Loading
Loading