|
| 1 | +#' Add grouping column using a function |
| 2 | +#' |
| 3 | +#' @inheritParams run_eval |
| 4 | +#' |
| 5 | +#' @param fun Function used to define groups. Either (1) a quoted or character |
| 6 | +#' name referencing a function (e.g., [group_by_time()], [group_by_dose()], or a |
| 7 | +#' custom function), or (2) an anonymous function; see examples. |
| 8 | +#' @param label column name of grouper column in dataset |
| 9 | +#' @param ... Additional arguments passed onto `fun`. See the respective |
| 10 | +#' grouping functions for more details. E.g. for `group_by_time`, need a |
| 11 | +#' `bins` argument. |
| 12 | +#' |
| 13 | +#' @details |
| 14 | +#' |
| 15 | +#' All functions supplied to `add_grouping_column()` must take at least the |
| 16 | +#' argument `data`, and return a numeric vector (or a vector that can be cast to |
| 17 | +#' numeric) of the same length as the number of rows in `data`, which will be |
| 18 | +#' used as the grouping column. |
| 19 | +#' |
| 20 | +#' @returns data.frame |
| 21 | +#' @seealso [group_by_time()], [group_by_dose()] |
| 22 | +#' @examples |
| 23 | +#' # group_by_dose: |
| 24 | +#' add_grouping_column(nm_busulfan, fun = group_by_dose, label = "group") |
| 25 | +#' |
| 26 | +#' # group_by_time: |
| 27 | +#' add_grouping_column(nm_busulfan, fun = "group_by_time", label = "group") |
| 28 | +#' |
| 29 | +#' # Anonymous function: |
| 30 | +#' add_grouping_column( |
| 31 | +#' nm_busulfan, |
| 32 | +#' fun = function(data) { |
| 33 | +#' as.numeric(cut( |
| 34 | +#' data$TIME, breaks = c(0, 24, 48, 72, 96, Inf), include.lowest = TRUE |
| 35 | +#' )) |
| 36 | +#' }, |
| 37 | +#' label = "group" |
| 38 | +#' ) |
| 39 | +#' |
| 40 | +#' @export |
| 41 | +add_grouping_column <- function( |
| 42 | + data, |
| 43 | + fun = group_by_time, |
| 44 | + label = "group", |
| 45 | + ... |
| 46 | +) { |
| 47 | + if(label %in% names(data)) { |
| 48 | + cli::cli_alert_warning("Overwriting {.field {label}} column in {.arg data}.") |
| 49 | + } |
| 50 | + if(inherits(fun, "character")) { |
| 51 | + fun <- get(fun) |
| 52 | + } |
| 53 | + data[[label]] <- fun(data, ...) |
| 54 | + data |
| 55 | +} |
| 56 | + |
| 57 | +#' Group data by time using bin separators |
| 58 | +#' |
| 59 | +#' @inheritParams add_grouping_column |
| 60 | +#' @inheritParams run_eval |
| 61 | +#' @param bins vector of bin separators. Suggestion to keep the last bin |
| 62 | +#' separator `Inf`, to ensure all points are included in a group. |
| 63 | +#' |
| 64 | +#' @returns a numeric vector of the same length as the number of rows in `data`. |
| 65 | +#' |
| 66 | +#' @examples |
| 67 | +#' group_by_time(nm_busulfan) |
| 68 | +#' |
| 69 | +#' @export |
| 70 | +group_by_time <- function( |
| 71 | + data, |
| 72 | + bins = c(0, 24, 48, 72, 96, Inf), |
| 73 | + dictionary = list("TIME" = "TIME"), |
| 74 | + ... |
| 75 | +) { |
| 76 | + as.numeric(cut(data[[dictionary$TIME]], breaks = bins, include.lowest = TRUE)) |
| 77 | +} |
| 78 | + |
| 79 | +#' Will create a separate group for each dose intervals that contains at least |
| 80 | +#' one sample |
| 81 | +#' |
| 82 | +#' @inheritParams add_grouping_column |
| 83 | +#' @inheritParams run_eval |
| 84 | +#' |
| 85 | +#' @returns a numeric vector of the same length as the number of rows in `data`. |
| 86 | +#' |
| 87 | +#' @examples |
| 88 | +#' group_by_dose(nm_busulfan) |
| 89 | +#' |
| 90 | +#' @export |
| 91 | +group_by_dose <- function( |
| 92 | + data, |
| 93 | + dictionary = list("ID" = "ID", "EVID" = "EVID", "TIME" = "TIME"), |
| 94 | + ... |
| 95 | +) { |
| 96 | + data |> |
| 97 | + dplyr::group_by(dplyr::pick(dictionary$ID)) |> |
| 98 | + dplyr::mutate(`_dose_idx` = cumsum(.data[[dictionary$EVID]])) |> |
| 99 | + dplyr::group_by(dplyr::pick(dictionary$ID, "_dose_idx")) |> |
| 100 | + dplyr::mutate(`_has_sample` = any(.data[[dictionary$EVID]] == 0)) |> |
| 101 | + dplyr::group_by(dplyr::pick(dictionary$ID)) |> |
| 102 | + dplyr::mutate( |
| 103 | + `_group` = cumsum(.data[[dictionary$EVID]] == 1 & .data$`_has_sample`) |
| 104 | + ) |> |
| 105 | + dplyr::pull(.data$`_group`) |
| 106 | +} |
0 commit comments