Skip to content

Commit 3785839

Browse files
committed
Added functions from darthtools
1 parent df84698 commit 3785839

File tree

1 file changed

+218
-6
lines changed

1 file changed

+218
-6
lines changed

R/Functions.R

Lines changed: 218 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,226 @@ format_table_cea <- function(table_cea) {
267267
"Incremental QALYs",
268268
"ICER ($/QALY)")
269269

270-
table_cea$`Costs ($)` <- comma(round(table_cea$`Costs ($)`, 0))
271-
table_cea$`Incremental Costs ($)` <- comma(round(table_cea$`Incremental Costs ($)`, 0))
270+
table_cea$`Costs ($)` <- scales::comma(round(table_cea$`Costs ($)`, 0))
271+
table_cea$`Incremental Costs ($)` <- scales::comma(round(table_cea$`Incremental Costs ($)`, 0))
272272
table_cea$QALYs <- round(table_cea$QALYs, 2)
273273
table_cea$`Incremental QALYs` <- round(table_cea$`Incremental QALYs`, 2)
274-
table_cea$`ICER ($/QALY)` <- comma(round(table_cea$`ICER ($/QALY)`, 0))
274+
table_cea$`ICER ($/QALY)` <- scales::comma(round(table_cea$`ICER ($/QALY)`, 0))
275275
return(table_cea)
276276
}
277277

278+
################################################################################
279+
################# FUNCTIONS INCLUDED IN DARTHTOOLS #############################
280+
################################################################################
281+
#' Within-cycle correction (WCC)
282+
#'
283+
#' \code{gen_wcc} generates a vector of within-cycle corrections (WCC).
284+
#'
285+
#' @param n_cycles number of cycles
286+
#' @param method The method to be used for within-cycle correction.
287+
#'
288+
#' @return A vector of length \code{n_cycles + 1} with within-cycle corrections
289+
#'
290+
#' @details
291+
#' The default method is an implementation of Simpson's 1/3rd rule that
292+
#' generates a vector with the first and last entry with 1/3 and the odd and
293+
#' even entries with 4/3 and 2/3, respectively.
294+
#'
295+
#' Method "\code{half-cycle}" is the half-cycle correction method that
296+
#' generates a vector with the first and last entry with 1/2 and the rest equal
297+
#' to 1.
298+
#'
299+
#' Method "\code{none}" does not implement any within-cycle correction and
300+
#' generates a vector with ones.
301+
#'
302+
#' @references
303+
#' \enumerate{
304+
#' \item Elbasha EH, Chhatwal J. Myths and misconceptions of within-cycle
305+
#' correction: a guide for modelers and decision makers. Pharmacoeconomics.
306+
#' 2016;34(1):13-22.
307+
#' \item Elbasha EH, Chhatwal J. Theoretical foundations and practical
308+
#' applications of within-cycle correction methods. Med Decis Mak.
309+
#' 2016;36(1):115-131.
310+
#' }
311+
#'
312+
#' @examples
313+
#' # Number of cycles
314+
#' n_cycles <- 10
315+
#' gen_wcc(n_cycles = n_cycles, method = "Simpson1/3")
316+
#' gen_wcc(n_cycles = n_cycles, method = "half-cycle")
317+
#' gen_wcc(n_cycles = n_cycles, method = "none")
318+
#'
319+
#' @export
320+
gen_wcc <- function (n_cycles, method = c("Simpson1/3", "half-cycle", "none"))
321+
{
322+
if (n_cycles <= 0) {
323+
stop("Number of cycles should be positive")
324+
}
325+
method <- match.arg(method)
326+
n_cycles <- as.integer(n_cycles)
327+
if (method == "Simpson1/3") {
328+
v_cycles <- seq(1, n_cycles + 1)
329+
v_wcc <- ((v_cycles%%2) == 0) * (2/3) + ((v_cycles%%2) !=
330+
0) * (4/3)
331+
v_wcc[1] <- v_wcc[n_cycles + 1] <- 1/3
332+
}
333+
if (method == "half-cycle") {
334+
v_wcc <- rep(1, n_cycles + 1)
335+
v_wcc[1] <- v_wcc[n_cycles + 1] <- 0.5
336+
}
337+
if (method == "none") {
338+
v_wcc <- rep(1, n_cycles + 1)
339+
}
340+
return(v_wcc)
341+
}
342+
343+
function (r, t = 1)
344+
{
345+
if ((sum(r < 0) > 0)) {
346+
stop("rate not greater than or equal to 0")
347+
}
348+
p <- 1 - exp(-r * t)
349+
return(p)
350+
}
351+
352+
#' Convert a rate to a probability
353+
#'
354+
#' \code{rate_to_prob} convert a rate to a probability.
355+
#'
356+
#' @param r rate
357+
#' @param t time/ frequency
358+
#' @return a scalar or vector with probabilities
359+
#' @examples
360+
#' # Annual rate to monthly probability
361+
#' r_year <- 0.3
362+
#' r_month <- rate_to_prob(r = r_year, t = 1/12)
363+
#' r_month
364+
#' @export
365+
rate_to_prob <- function(r, t = 1){
366+
if ((sum(r < 0) > 0)){
367+
stop("rate not greater than or equal to 0")
368+
}
369+
p <- 1 - exp(- r * t)
370+
return(p)
371+
}
372+
373+
#' Check if transition array is valid
374+
#'
375+
#' \code{check_transition_probability} checks if transition probabilities are in \[0, 1\].
376+
#'
377+
#' @param a_P A transition probability array/ matrix.
378+
#' @param err_stop Logical variable to stop model run if set up as TRUE. Default = FALSE.
379+
#' @param verbose Logical variable to indicate print out of messages.
380+
#' Default = FALSE
381+
#'
382+
#' @return
383+
#' This function stops if transition probability array is not valid and shows
384+
#' what are the entries that are not valid
385+
#' @export
386+
check_transition_probability <- function(a_P,
387+
err_stop = FALSE,
388+
verbose = FALSE) {
389+
390+
a_P <- as.array(a_P)
391+
392+
# Verify if a_P is 2D or 3D matrix
393+
n_dim <- length(dim(a_P))
394+
# If a_P is a 2D matrix, convert to a 3D array
395+
if (n_dim < 3){
396+
a_P <- array(a_P, dim = list(nrow(a_P), ncol(a_P), 1),
397+
dimnames = list(rownames(a_P), colnames(a_P), "Time independent"))
398+
}
399+
# Check which entries are not valid
400+
m_indices_notvalid <- arrayInd(which(a_P < 0 | a_P > 1),
401+
dim(a_P))
402+
403+
if(dim(m_indices_notvalid)[1] != 0){
404+
v_rows_notval <- rownames(a_P)[m_indices_notvalid[, 1]]
405+
v_cols_notval <- colnames(a_P)[m_indices_notvalid[, 2]]
406+
v_cycles_notval <- dimnames(a_P)[[3]][m_indices_notvalid[, 3]]
407+
408+
df_notvalid <- data.frame(`Transition probabilities not valid:` =
409+
matrix(paste0(paste(v_rows_notval, v_cols_notval, sep = "->"),
410+
"; at cycle ",
411+
v_cycles_notval), ncol = 1),
412+
check.names = FALSE)
413+
414+
if(err_stop) {
415+
stop("Not valid transition probabilities\n",
416+
paste(capture.output(df_notvalid), collapse = "\n"))
417+
}
418+
419+
if(verbose){
420+
warning("Not valid transition probabilities\n",
421+
paste(capture.output(df_notvalid), collapse = "\n"))
422+
}
423+
}
424+
}
425+
426+
#' Check if the sum of transition probabilities equal to one.
427+
#'
428+
#' \code{check_sum_of_transition_array} checks if each of the rows of the
429+
#' transition matrices sum to one.
430+
#'
431+
#' @param a_P A transition probability array/ matrix.
432+
#' @param n_states Number of health states in a Markov trace, appropriate for Markov models.
433+
#' @param n_rows Number of rows (individuals), appropriate for microsimulation models.
434+
#' @param n_cycles Number of cycles.
435+
#' @param err_stop Logical variable to stop model run if set up as TRUE.
436+
#' Default = TRUE.
437+
#' @param verbose Logical variable to indicate print out of messages.
438+
#' Default = TRUE
439+
#' @return
440+
#' The transition probability array and the cohort trace matrix.
441+
#' @export
442+
check_sum_of_transition_array <- function(a_P,
443+
n_rows = NULL,
444+
n_states = NULL,
445+
n_cycles,
446+
err_stop = TRUE,
447+
verbose = TRUE) {
448+
449+
if (!is.null(n_rows) & !is.null(n_states)) {
450+
stop("Pick either n_rows or n_states, not both.")
451+
}
452+
453+
if (is.null(n_rows) & is.null(n_states)) {
454+
stop("Need to specify either n_rows or n_states, but not both.")
455+
}
456+
457+
if (!is.null(n_rows)) {
458+
n_states <- n_rows
459+
}
460+
461+
a_P <- as.array(a_P)
462+
d <- length(dim(a_P))
463+
# For matrix
464+
if (d == 2) {
465+
valid <- sum(rowSums(a_P))
466+
if (abs(valid - n_states) > 0.01) {
467+
if(err_stop) {
468+
stop("This is not a valid transition matrix")
469+
}
470+
471+
if(verbose){
472+
warning("This is not a valid transition matrix")
473+
}
474+
}
475+
} else {
476+
# For array
477+
valid <- (apply(a_P, d, function(x) sum(rowSums(x))) == n_states)
478+
if (!isTRUE(all.equal(as.numeric(sum(valid)), as.numeric(n_cycles)))) {
479+
if(err_stop) {
480+
stop("This is not a valid transition array")
481+
}
482+
483+
if(verbose){
484+
warning("This is not a valid transition array")
485+
}
486+
}
487+
}
488+
}
489+
278490
################################################################################
279491
################## FUNCTIONS INCLUDED IN DAMPACK ###############################
280492
################################################################################
@@ -966,7 +1178,7 @@ plot.icers <- function(x,
9661178
}
9671179

9681180
icer_plot <- icer_plot +
969-
geom_label_repel(data = lab_data,
1181+
ggrepel::geom_label_repel(data = lab_data,
9701182
aes_(label = as.name(strat_name)),
9711183
size = 3,
9721184
show.legend = FALSE,
@@ -1179,7 +1391,7 @@ plot.psa <- function(x,
11791391
df_list_ell <- lapply(strategies, function(s) {
11801392
strat_specific_df <- ce_df[ce_df$Strategy == s, ]
11811393
els <- with(strat_specific_df,
1182-
ellipse(cor(Effectiveness, Cost),
1394+
ellipse::ellipse(cor(Effectiveness, Cost),
11831395
scale = c(sd(Effectiveness), sd(Cost)),
11841396
centre = c(mean(Effectiveness), mean(Cost))))
11851397
data.frame(els, group = s, stringsAsFactors = FALSE)
@@ -1832,7 +2044,7 @@ add_common_aes <- function(gplot, txtsize, scale_name = waiver(),
18322044
#' @return a character vector giving a label for each input value
18332045
labfun <- function(x) {
18342046
if (any(x > 999, na.rm = TRUE)) {
1835-
comma(x)
2047+
scales::comma(x)
18362048
} else {
18372049
x
18382050
}

0 commit comments

Comments
 (0)