diff --git a/R/internal.R b/R/internal.R index 28fcbe2..e4c714f 100644 --- a/R/internal.R +++ b/R/internal.R @@ -204,6 +204,22 @@ (maxval - minval) + start_continuous_endpoint } +.logTicks <- function(range) { + a <- floor(log2(range[1])) + b <- ceiling(log2(range[2])) + steps <- unique(round(pretty(c(a, b)))) + return((2 ^ steps)) +} + +.log10Ticks <- function(range) { + range <- log10(range) + get_axp <- function(x) 10^c(floor(x[1]), ceiling(x[2])) + n <- ifelse(range[2] > 4, 1, 2) + steps <- axTicks(side = 1, usr = range, axp = c(get_axp(range), n = n), + log = TRUE) + return((steps)) +} + # Computes the continuous information .compute_continuous <- function( hce_dat, meta, ecdf_mod, step_outcomes, last_outcome, arm_levels) { @@ -308,9 +324,11 @@ binary_data <- rbind(data.frame("outcome" = last_outcome, "arm" = actv, + "value" = 1, actv_point), data.frame("outcome" = last_outcome, "arm" = ctrl, + "value" = 1, ctrl_point) ) @@ -438,7 +456,8 @@ .maraca_from_hce_data <- function(x, last_outcome, arm_levels, fixed_followup_days, compute_win_odds, step_types = "tte", - last_type = "continuous") { + last_type = "continuous", + lowerBetter = FALSE) { checkmate::assert_string(last_outcome) checkmate::assert_names(names(x), @@ -478,7 +497,8 @@ fixed_followup_days = fixed_followup_days, compute_win_odds = compute_win_odds, step_types = step_types, - last_type = last_type + last_type = last_type, + lowerBetter = lowerBetter ) return(maraca_obj) diff --git a/R/internal_winOdds.R b/R/internal_winOdds.R index cbc6da8..72279e5 100644 --- a/R/internal_winOdds.R +++ b/R/internal_winOdds.R @@ -35,11 +35,22 @@ # Computes the win odds from the internal data. .compute_win_odds <- function(hce_dat, arm_levels, - step_outcomes, last_outcome) { + step_outcomes, last_outcome, + lowerBetter) { `%>%` <- dplyr::`%>%` hce_dat <- base::as.data.frame(hce_dat) + idx_last <- hce_dat$outcome == last_outcome + + # Reversing continous outcome variables if lower is considered better + if (lowerBetter) { + hce_dat[idx_last, "value"] <- + (min(hce_dat[idx_last, "value"], na.rm = TRUE) - + hce_dat[idx_last, "value"] + + max(hce_dat[idx_last, "value"], na.rm = TRUE)) + } + hce_dat <- .with_ordered_column(hce_dat) fit <- hce::calcWO(x = hce_dat, AVAL = "ordered", TRTP = "arm", @@ -56,7 +67,7 @@ endpoints <- c(step_outcomes, last_outcome) labs <- c(sapply(head(seq_along(endpoints), -1), function(i) { paste(endpoints[1:i], collapse = " +\n") - }), "All") + }), "Overall") hce_dat <- hce_dat %>% dplyr::mutate_at(dplyr::vars(outcome), factor, levels = c(endpoints, "X")) @@ -88,13 +99,17 @@ wo$outcome <- endpoints[i] wo$GROUP <- labs[i] wo %>% - dplyr::rename(dplyr::all_of(c(wins = "WIN", losses = "LOSS", - ties = "TIE"))) %>% - tidyr::pivot_longer(cols = c(wins, losses, ties)) %>% - dplyr::mutate_at(dplyr::vars(name), factor, - levels = c("wins", "losses", "ties")) + dplyr::rename(dplyr::all_of(c(A_wins = "WIN", P_wins = "LOSS", + Ties = "TIE"))) %>% + tidyr::pivot_longer(cols = c("A_wins", "P_wins", "Ties"), + names_to = "name", values_to = "value") + # %>% + # dplyr::mutate_at(dplyr::vars(name), factor, + # levels = c("wins", "losses", "ties")) })) + wo_bar <- .label_win_odds_plots(wo_bar, arm_levels) + wins_forest$GROUP <- factor(wins_forest$GROUP, levels = rev(labs)) wins_forest$method <- factor(wins_forest$method, levels = c("win ratio", "win odds")) @@ -143,21 +158,26 @@ # Calculate percentage results wo_bar_nc$percentage <- 100 * (wo_bar_nc$value / wo_bar_nc$total) + wo_bar_nc <- .label_win_odds_plots(wo_bar_nc, arms) + + return(wo_bar_nc) +} + +.label_win_odds_plots <- function(bar_data, arms) { labels <- c(paste(arms["active"], "wins"), paste(arms["control"], "wins"), "Ties") - wo_bar_nc$name <- ifelse(wo_bar_nc$name == "A_wins", - labels[1], - ifelse(wo_bar_nc$name == "P_wins", - labels[2], labels[3])) + bar_data$name <- ifelse(bar_data$name == "A_wins", + labels[1], + ifelse(bar_data$name == "P_wins", + labels[2], labels[3])) - wo_bar_nc$name <- factor(wo_bar_nc$name, levels = labels) + bar_data$name <- factor(bar_data$name, levels = labels) - return(wo_bar_nc) + return(bar_data) } - # The main plotting function creating the component plot .create_component_plot <- function(wo_bar_nc, endpoints, theme) { @@ -193,7 +213,12 @@ } # Create forest plot part of cumulative plot -.create_forest_plot <- function(wins_forest, theme) { +.create_forest_plot <- function(wins_forest, theme, reverse) { + + if (reverse) { + wins_forest$GROUP <- factor(wins_forest$GROUP, + levels = rev(levels(wins_forest$GROUP))) + } plot <- ggplot(data = wins_forest) + geom_errorbar(aes(x = GROUP, y = value, ymin = LCL, ymax = UCL, @@ -228,14 +253,18 @@ } # Create bar plot part of cumulative plot -.create_bar_plot <- function(wo_bar, theme) { +.create_bar_plot <- function(wo_bar, theme, reverse) { + + if (reverse) { + wo_bar$GROUP <- factor(wo_bar$GROUP, levels = rev(levels(wo_bar$GROUP))) + } plot <- ggplot(data = wo_bar, aes(x = GROUP, y = percentage, fill = name)) + geom_bar(stat = "identity", position = position_dodge(), width = .9) + coord_flip() + # make bar plot horizontal geom_text(aes(label = round(percentage, 1)), position = ggplot2::position_dodge(width = .9), - vjust = 0.5, hjust = 1.2) + vjust = 0.5, hjust = -0.2) plot <- switch(theme, "maraca" = .theme_maraca_cp(plot), diff --git a/R/maraca.R b/R/maraca.R index 5c3423d..3ef0af6 100644 --- a/R/maraca.R +++ b/R/maraca.R @@ -36,6 +36,12 @@ #' @param last_type A single string giving the type of the last outcome. #' Possible values are "continuous" (default), "binary" or #' "multinomial". +#' @param lowerBetter Flag for the final outcome variable, indicating if +#' lower values are considered better/advantageous. +#' This flag is need to make sure the win odds are +#' calculated correctly. +#' Default value is FALSE, meaning higher values +#' are considered advantageous. #' @param tte_outcomes Deprecated and substituted by the more general #' 'step_outcomes'. A vector of strings containing the #' time-to-event outcome labels. The order is kept for the @@ -74,6 +80,7 @@ maraca <- function( compute_win_odds = FALSE, step_types = "tte", last_type = "continuous", + lowerBetter = FALSE, tte_outcomes = lifecycle::deprecated(), continuous_outcome = lifecycle::deprecated() ) { @@ -122,6 +129,8 @@ maraca <- function( choices = c("continuous", "binary"), empty.ok = FALSE) + checkmate::assert_flag(lowerBetter) + if (!(length(fixed_followup_days) %in% c(1, length(step_outcomes[step_types == "tte"])))) { stop(paste("fixed_followup_days needs to be either a single value or", @@ -200,7 +209,8 @@ maraca <- function( "wins_forest" = NULL, "wo_bar" = NULL) if (compute_win_odds) { win_odds <- .compute_win_odds(hce_dat, arm_levels, - step_outcomes, last_outcome) + step_outcomes, last_outcome, + lowerBetter) } return( @@ -219,7 +229,8 @@ maraca <- function( win_odds = win_odds[["win_odds"]], win_odds_outcome = win_odds[["win_odds_outcome"]], wins_forest = win_odds[["wins_forest"]], - wo_bar = win_odds[["wo_bar"]] + wo_bar = win_odds[["wo_bar"]], + lowerBetter = lowerBetter ), class = c("maraca") ) @@ -269,8 +280,10 @@ print.maraca <- function(x, ...) { #' @param obj an object of S3 class 'maraca' #' @param continuous_grid_spacing_x The spacing of the x grid to use for the #' continuous section of the plot. -#' @param trans the transformation to apply to the data before plotting. -#' The accepted values are the same that ggplot2::scale_x_continuous +#' @param trans the transformation to apply to the x-axis scale for the last +#' outcome. Possible values are "identity", "log" (only for continuous +#' endpoint), "log10" (only for continuous endpoint), "sqrt" (only for +#' continuous endpoint) and "reverse". The default value is "identity". #' @param density_plot_type which type of plot to display in the continuous #' part of the plot. Options are "default", "violin", "box", "scatter". #' @param vline_type what the vertical dashed line should represent. Accepts @@ -300,8 +313,8 @@ print.maraca <- function(x, ...) { #' @export plot_maraca <- function( obj, continuous_grid_spacing_x = NULL, - trans = "identity", - density_plot_type = "default", + trans = c("identity", "log", "log10", "sqrt", "reverse")[1], + density_plot_type = c("default", "violin", "box", "scatter")[1], vline_type = NULL, theme = "maraca") { @@ -313,6 +326,10 @@ plot_maraca <- function( } checkmate::assert_string(trans) + checkmate::assert_subset(trans, + choices = c("identity", "log", "log10", + "sqrt", "reverse"), + empty.ok = FALSE) aes <- ggplot2::aes `%>%` <- dplyr::`%>%` @@ -325,6 +342,11 @@ plot_maraca <- function( last_data <- obj$data_last_outcome last_type <- obj$last_type + if (last_type == "binary" && trans %in% c("log", "log10", "sqrt")) { + stop(paste(trans, "transformation only implemented for continuous", + "last endpoint.")) + } + vline_type <- switch(last_type, "continuous" = .checks_continuous_outcome(density_plot_type, @@ -339,16 +361,15 @@ plot_maraca <- function( meta[meta$outcome == obj$last_outcome, ]$startx if (is.null(continuous_grid_spacing_x)) { - continuous_grid_spacing_x <- ifelse(last_type == "continuous", 10, 0.1) + continuous_grid_spacing_x <- 10 } - plotdata_ecdf <- ecdf_mod$data[, c("outcome", "arm", + plotdata_ecdf <- ecdf_mod$data[, c("outcome", "arm", "value", "adjusted.time", "step_values", "type")] - names(plotdata_ecdf) <- c("outcome", "arm", "x", "y", "type") - plotdata_last <- last_data$data[, c("outcome", "arm", "x", "y")] + names(plotdata_ecdf) <- c("outcome", "arm", "value", "x", "y", "type") + plotdata_last <- last_data$data[, c("outcome", "arm", "value", "x", "y")] plotdata_last$type <- last_type - names(plotdata_last) <- c("outcome", "arm", "x", "y", "type") # Add points at (0, 0) on both curves so that they start from the origin add_points <- plotdata_ecdf %>% @@ -399,7 +420,7 @@ plot_maraca <- function( plotdata_ecdf <- plotdata_ecdf[order(plotdata_ecdf$x), ] - plotdata <- as.data.frame(rbind(plotdata_ecdf, plotdata_last)) + plotdata <- rbind(plotdata_ecdf, plotdata_last) scale <- sign(log10(continuous_grid_spacing_x)) * floor( abs(log10(continuous_grid_spacing_x)) @@ -407,18 +428,78 @@ plot_maraca <- function( if (last_type == "continuous") { - minor_grid <- .minor_grid( - last_data$data$value, scale, continuous_grid_spacing_x - ) - - range <- c(min(last_data$data$value, na.rm = TRUE), - max(last_data$data$value, na.rm = TRUE)) + range <- c(min(plotdata_last$value, na.rm = TRUE), + max(plotdata_last$value, na.rm = TRUE)) + + if (trans %in% c("log", "log10", "sqrt")) { + minor_grid <- switch(trans, + "log" = .logTicks(range), + "log10" = .log10Ticks(range), + "sqrt" = pretty(range)) + minor_grid <- minor_grid[minor_grid >= range[1] & + minor_grid <= range[2]] + minor_grid_x <- eval(parse(text = paste0(trans, "(minor_grid)"))) + } else { + minor_grid <- .minor_grid(plotdata_last$value, scale, + continuous_grid_spacing_x) + minor_grid_x <- minor_grid + } } else if (last_type == "binary") { - minor_grid <- seq(0, 100, continuous_grid_spacing_x) - range <- c(0, 100) + lowest_value <- min(plotdata_last$value, na.rm = TRUE) + highest_value <- max(plotdata_last$value, na.rm = TRUE) + range <- c(min(0, floor(lowest_value / 10) * 10), + max(100, ceiling(highest_value / 10) * 10)) + minor_grid <- seq(range[1], range[2], continuous_grid_spacing_x) + minor_grid_x <- minor_grid + + } + + vline_data <- NULL + if (vline_type == "median") { + vline_data <- last_data$meta %>% + dplyr::select("x" = median, arm) + } else if (vline_type == "mean") { + vline_data <- last_data$meta %>% + dplyr::select("x" = median, arm) + } + + if (trans %in% c("log", "log10", "sqrt")) { + if (range[1] < 0) { + warning(paste("Continuous endpoint has negative values - the", + trans, "transformation will result in missing values")) + } + plotdata_last$value <- eval(parse(text = paste0(trans, + "(plotdata_last$value)"))) + range <- c(min(plotdata_last$value, na.rm = TRUE), + max(plotdata_last$value, na.rm = TRUE)) + plotdata_last$x <- .to_rangeab(plotdata_last$value, start_last_endpoint, + range[1], range[2]) + + if (!is.null(vline_data)) { + vline_data$x <- eval(parse(text = paste0(trans, "(vline_data$x)"))) + } + } + + if (trans == "reverse") { + if (!is.null(win_odds) && !obj$lowerBetter) { + message(paste("Last endpoint axis has been reversed, which might", + "indicate that lower values are considered advantageuos.", + "Note that the win odds were calculated assuming that", + "higher values are better. If that is not correct, please", + "use the parameter lowerBetter = TRUE in the", + "maraca function.")) + } + + minor_grid_x <- rev(minor_grid_x) + minor_grid <- rev(minor_grid) + plotdata_last$x <- start_last_endpoint - plotdata_last$x + 100 + + if (!is.null(vline_data)) { + vline_data$x <- start_last_endpoint - plotdata_last$x + 100 + } } # Plot the information in the Maraca plot @@ -428,26 +509,14 @@ plot_maraca <- function( color = "grey80" ) - if (vline_type == "median") { - plot <- plot + - ggplot2::geom_vline( - mapping = ggplot2::aes( - xintercept = median, - color = arm - ), - data = last_data$meta, - linetype = "dashed", - linewidth = 0.8, - show.legend = FALSE - ) - } else if (vline_type == "mean") { + if (!is.null(vline_data)) { plot <- plot + ggplot2::geom_vline( mapping = ggplot2::aes( - xintercept = average, + xintercept = x, color = arm ), - data = last_data$meta, + data = vline_data, linetype = "dashed", linewidth = 0.8, show.legend = FALSE @@ -456,14 +525,15 @@ plot_maraca <- function( for (outcome in step_outcomes[which_tte]) { plot <- plot + - ggplot2::geom_step(data = plotdata[plotdata$outcome == outcome, ], + ggplot2::geom_step(data = + plotdata_ecdf[plotdata_ecdf$outcome == outcome, ], aes(x = x, y = y, color = arm)) } if (length(which_binary) > 0) { - tmp <- plotdata[plotdata$outcome %in% step_outcomes[which_binary], ] - + tmp <- plotdata_ecdf[plotdata_ecdf$outcome %in% + step_outcomes[which_binary], ] tmp <- tmp[order(tmp$x), ] if (step_types[length(step_types)] == "binary") { @@ -500,7 +570,7 @@ plot_maraca <- function( if (step_types[length(step_types)] == "binary") { - tmp <- plotdata %>% + tmp <- plotdata_ecdf %>% dplyr::filter(outcome == step_outcomes[length(step_types)]) %>% dplyr::group_by(arm) %>% dplyr::slice_tail(n = -1) %>% @@ -543,19 +613,19 @@ plot_maraca <- function( } else if (density_plot_type == "violin") { plot <- plot + ggplot2::geom_violin( - data = plotdata[plotdata$type == "continuous", ], + data = plotdata_last, aes(x = x, y = y, colour = arm, fill = arm), alpha = 0.5 ) } else if (density_plot_type == "box") { plot <- plot + ggplot2::geom_boxplot( - data = plotdata[plotdata$type == "continuous", ], + data = plotdata_last, aes(x = x, y = y, colour = arm, fill = arm), alpha = 0.5 ) } else if (density_plot_type == "scatter") { plot <- plot + ggplot2::geom_jitter( - data = plotdata[plotdata$type == "continuous", ], + data = plotdata_last, aes(x = x, y = y, color = arm), # Jittering only vertically, keep the correct x-value width = 0 @@ -569,27 +639,28 @@ plot_maraca <- function( return(as.character(round(x, -s + 1))) } ) + + m_breaks <- .to_rangeab( + minor_grid_x, + start_last_endpoint, + range[1], + range[2] + ) + + if (trans == "reverse") { + m_breaks <- start_last_endpoint - m_breaks + 100 + } + plot <- plot + ggplot2::scale_x_continuous( limits = c(0, 100), breaks = c(meta$proportion / 2 + meta$startx + 0.1), labels = c(obj$step_outcomes, obj$last_outcome), - minor_breaks = .to_rangeab( - minor_grid, - start_last_endpoint, - range[1], - range[2] - ), - trans = trans + minor_breaks = m_breaks ) + ggplot2::annotate( geom = "text", - x = .to_rangeab( - minor_grid, - start_last_endpoint, - range[1], - range[2] - ), + x = m_breaks, y = 0, label = labels, color = "grey60" @@ -667,7 +738,7 @@ validate_maraca_plot <- function(x, ...) { proportions <- diff(pb$data[[1]][, c("xintercept")]) names(proportions) <- unique(x$data$outcome) - arms <- levels(pb$plot$data[, pb$plot$labels$colour]) + arms <- levels(unlist(pb$plot$data[, pb$plot$labels$colour])) tte_data <- .create_validation_tte(layers, x, arms) binary_step_data <- .create_validation_binary_step(layers, x, arms) @@ -711,8 +782,10 @@ validate_maraca_plot <- function(x, ...) { #' @param \dots not used #' @param continuous_grid_spacing_x The spacing of the x grid to use for the #' continuous section of the plot. -#' @param trans the transformation to apply to the data before plotting. -#' The accepted values are the same that ggplot2::scale_x_continuous +#' @param trans the transformation to apply to the x-axis scale for the last +#' outcome. Possible values are "identity", "log" (only for continuous +#' endpoint), "log10" (only for continuous endpoint), "sqrt" (only for +#' continuous endpoint) and "reverse". The default value is "identity". #' @param density_plot_type The type of plot to use to represent the density. #' Accepts "default", "violin", "box" and "scatter". #' @param vline_type what the vertical dashed line should represent. Accepts @@ -741,8 +814,10 @@ validate_maraca_plot <- function(x, ...) { #' #' @export plot.maraca <- function( - x, continuous_grid_spacing_x = 10, trans = "identity", - density_plot_type = "default", + x, + continuous_grid_spacing_x = 10, + trans = c("identity", "log", "log10", "sqrt", "reverse")[1], + density_plot_type = c("default", "violin", "box", "scatter")[1], vline_type = NULL, theme = "maraca", ...) { @@ -765,8 +840,10 @@ plot.maraca <- function( #' "active" and "control". #' @param continuous_grid_spacing_x The spacing of the x grid to use for the #' continuous section of the plot. -#' @param trans the transformation to apply to the data before plotting. -#' The accepted values are the same that ggplot2::scale_x_continuous +#' @param trans the transformation to apply to the x-axis scale for the last +#' outcome. Possible values are "identity", "log" (only for continuous +#' endpoint), "log10" (only for continuous endpoint), "sqrt" (only for +#' continuous endpoint) and "reverse". The default value is "identity". #' @param density_plot_type The type of plot to use to represent the density. #' Accepts "default", "violin", "box" and "scatter". #' @param vline_type what the vertical dashed line should represent. Accepts @@ -796,6 +873,12 @@ plot.maraca <- function( #' For more details, check the vignette called #' "Maraca Plots - Themes and Styling". #' [companion vignette for package users](themes.html) +#' @param lowerBetter Flag for the final outcome variable, indicating if +#' lower values are considered better/advantageous. +#' This flag is need to make sure the win odds are +#' calculated correctly. +#' Default value is FALSE, meaning higher values +#' are considered advantageous. #' @param continuous_outcome Deprecated and substituted by the more general #' 'last_outcome'. A single string containing the #' continuous outcome label. @@ -814,14 +897,17 @@ plot.maraca <- function( plot.hce <- function(x, last_outcome = "C", arm_levels = c(active = "A", control = "P"), continuous_grid_spacing_x = 10, - trans = "identity", - density_plot_type = "default", + trans = c("identity", "log", "log10", + "sqrt", "reverse")[1], + density_plot_type = c("default", "violin", + "box", "scatter")[1], vline_type = NULL, fixed_followup_days = NULL, compute_win_odds = FALSE, step_types = "tte", last_type = "continuous", theme = "maraca", + lowerBetter = FALSE, continuous_outcome = lifecycle::deprecated(), ...) { @@ -835,7 +921,8 @@ plot.hce <- function(x, last_outcome = "C", fixed_followup_days, compute_win_odds, step_types = step_types, - last_type = last_type) + last_type = last_type, + lowerBetter = lowerBetter) plot_maraca(maraca_obj, continuous_grid_spacing_x, trans, density_plot_type, vline_type, theme) diff --git a/R/winOddsPlots.R b/R/winOddsPlots.R index 5cec958..e82a90d 100644 --- a/R/winOddsPlots.R +++ b/R/winOddsPlots.R @@ -110,6 +110,12 @@ component_plot.maraca <- function(x, #' Options are "maraca", "color1", "color2" and none". #' For more details, check the vignette called #' "Maraca Plots - Plotting win odds". +#' @param lowerBetter Flag for the final outcome variable, indicating if +#' lower values are considered better/advantageous. +#' This flag is need to make sure the win odds are +#' calculated correctly. +#' Default value is FALSE, meaning higher values +#' are considered advantageous. #' @param continuous_outcome Deprecated and substituted by the more general #' 'last_outcome'. A single string containing the #' continuous outcome label. @@ -128,13 +134,15 @@ component_plot.hce <- function(x, last_outcome = "C", arm_levels = c(active = "A", control = "P"), fixed_followup_days = NULL, theme = "maraca", + lowerBetter = FALSE, continuous_outcome = lifecycle::deprecated(), ...) { # Create maraca object maraca_dat <- .maraca_from_hce_data(x, last_outcome, arm_levels, fixed_followup_days, - compute_win_odds = TRUE) + compute_win_odds = TRUE, + lowerBetter = lowerBetter) # Get win odds by outcome from maraca object win_odds_outcome <- maraca_dat$win_odds_outcome @@ -182,11 +190,14 @@ cumulative_plot.default <- function(x, ...) { #' Check the vignette "Maraca Plots - Plotting win odds" for more details. #' #' @param x an object of S3 class 'maraca'. -#' @param \dots not used #' @param theme Choose theme to style the plot. The default theme is "maraca". #' Options are "maraca", "color1", "color2" and none". #' For more details, check the vignette called #' "Maraca Plots - Plotting win odds". +#' @param reverse Flag indicating if the cumulated outcomes should be +#' displayed in order from top to bottom (FALSE, the default) +#' or in reverse (TRUE). +#' @param \dots not used #' @return Cumulative plot as a patchwork object. #' @examples #' @@ -208,7 +219,8 @@ cumulative_plot.default <- function(x, ...) { #' cumulative_plot(maraca_dat) #' #' @export -cumulative_plot.maraca <- function(x, theme = "maraca", ...) { +cumulative_plot.maraca <- function(x, theme = "maraca", + reverse = FALSE, ...) { # Check that win odds were calculated for the maraca object if (is.null(x[["wins_forest"]]) || is.null(x[["wo_bar"]])) { @@ -221,8 +233,8 @@ cumulative_plot.maraca <- function(x, theme = "maraca", ...) { wo_bar <- x$wo_bar wins_forest <- x$wins_forest # Create forest plot - plot_bar <- .create_bar_plot(wo_bar, theme) - plot_forest <- .create_forest_plot(wins_forest, theme) + plot_bar <- .create_bar_plot(wo_bar, theme, reverse) + plot_forest <- .create_forest_plot(wins_forest, theme, reverse) plot <- patchwork:::"|.ggplot"(plot_bar, plot_forest) + patchwork::plot_layout(widths = c(2.5, 1), nrow = 1) @@ -261,6 +273,15 @@ cumulative_plot.maraca <- function(x, theme = "maraca", ...) { #' Options are "maraca", "color1", "color2" and none". #' For more details, check the vignette called #' "Maraca Plots - Plotting win odds". +#' @param reverse Flag indicating if the cumulated outcomes should be +#' displayed in order from top to bottom (FALSE, the default) +#' or in reverse (TRUE). +#' @param lowerBetter Flag for the final outcome variable, indicating if +#' lower values are considered better/advantageous. +#' This flag is need to make sure the win odds are +#' calculated correctly. +#' Default value is FALSE, meaning higher values +#' are considered advantageous. #' @param continuous_outcome Deprecated and substituted by the more general #' 'last_outcome'. A single string containing the #' continuous outcome label. @@ -279,15 +300,18 @@ cumulative_plot.hce <- function(x, last_outcome = "C", arm_levels = c(active = "A", control = "P"), fixed_followup_days = NULL, theme = "maraca", + reverse = FALSE, + lowerBetter = FALSE, continuous_outcome = lifecycle::deprecated(), ...) { # Create maraca object maraca_dat <- .maraca_from_hce_data(x, last_outcome, arm_levels, fixed_followup_days, - compute_win_odds = TRUE) + compute_win_odds = TRUE, + lowerBetter = lowerBetter) - plot <- cumulative_plot(maraca_dat, theme = theme) + plot <- cumulative_plot(maraca_dat, theme = theme, reverse = reverse) return(plot) } diff --git a/man/component_plot.hce.Rd b/man/component_plot.hce.Rd index 43008fd..8b676fc 100644 --- a/man/component_plot.hce.Rd +++ b/man/component_plot.hce.Rd @@ -13,6 +13,7 @@ Check the vignette "Maraca Plots - Plotting win odds" for more details.} arm_levels = c(active = "A", control = "P"), fixed_followup_days = NULL, theme = "maraca", + lowerBetter = FALSE, continuous_outcome = lifecycle::deprecated(), ... ) @@ -45,6 +46,13 @@ Options are "maraca", "color1", "color2" and none". For more details, check the vignette called "Maraca Plots - Plotting win odds".} +\item{lowerBetter}{Flag for the final outcome variable, indicating if +lower values are considered better/advantageous. +This flag is need to make sure the win odds are +calculated correctly. +Default value is FALSE, meaning higher values +are considered advantageous.} + \item{continuous_outcome}{Deprecated and substituted by the more general 'last_outcome'. A single string containing the continuous outcome label.} diff --git a/man/cumulative_plot.hce.Rd b/man/cumulative_plot.hce.Rd index 82f27e7..13973b1 100644 --- a/man/cumulative_plot.hce.Rd +++ b/man/cumulative_plot.hce.Rd @@ -13,6 +13,8 @@ Check the vignette "Maraca Plots - Plotting win odds" for more details.} arm_levels = c(active = "A", control = "P"), fixed_followup_days = NULL, theme = "maraca", + reverse = FALSE, + lowerBetter = FALSE, continuous_outcome = lifecycle::deprecated(), ... ) @@ -45,6 +47,17 @@ Options are "maraca", "color1", "color2" and none". For more details, check the vignette called "Maraca Plots - Plotting win odds".} +\item{reverse}{Flag indicating if the cumulated outcomes should be +displayed in order from top to bottom (FALSE, the default) +or in reverse (TRUE).} + +\item{lowerBetter}{Flag for the final outcome variable, indicating if +lower values are considered better/advantageous. +This flag is need to make sure the win odds are +calculated correctly. +Default value is FALSE, meaning higher values +are considered advantageous.} + \item{continuous_outcome}{Deprecated and substituted by the more general 'last_outcome'. A single string containing the continuous outcome label.} diff --git a/man/cumulative_plot.maraca.Rd b/man/cumulative_plot.maraca.Rd index f400843..a268459 100644 --- a/man/cumulative_plot.maraca.Rd +++ b/man/cumulative_plot.maraca.Rd @@ -9,7 +9,7 @@ Note that for this plot, when creating the maraca object using the maraca() function, the argument "compute_win_odds" has to be set to TRUE. Check the vignette "Maraca Plots - Plotting win odds" for more details.} \usage{ -\method{cumulative_plot}{maraca}(x, theme = "maraca", ...) +\method{cumulative_plot}{maraca}(x, theme = "maraca", reverse = FALSE, ...) } \arguments{ \item{x}{an object of S3 class 'maraca'.} @@ -19,6 +19,10 @@ Options are "maraca", "color1", "color2" and none". For more details, check the vignette called "Maraca Plots - Plotting win odds".} +\item{reverse}{Flag indicating if the cumulated outcomes should be +displayed in order from top to bottom (FALSE, the default) +or in reverse (TRUE).} + \item{\dots}{not used} } \value{ diff --git a/man/maraca.Rd b/man/maraca.Rd index 20e698d..78e73e6 100644 --- a/man/maraca.Rd +++ b/man/maraca.Rd @@ -17,6 +17,7 @@ maraca( compute_win_odds = FALSE, step_types = "tte", last_type = "continuous", + lowerBetter = FALSE, tte_outcomes = lifecycle::deprecated(), continuous_outcome = lifecycle::deprecated() ) @@ -68,6 +69,13 @@ in the vector are "tte" (default) or "binary".} Possible values are "continuous" (default), "binary" or "multinomial".} +\item{lowerBetter}{Flag for the final outcome variable, indicating if +lower values are considered better/advantageous. +This flag is need to make sure the win odds are +calculated correctly. +Default value is FALSE, meaning higher values +are considered advantageous.} + \item{tte_outcomes}{Deprecated and substituted by the more general 'step_outcomes'. A vector of strings containing the time-to-event outcome labels. The order is kept for the diff --git a/man/plot.hce.Rd b/man/plot.hce.Rd index 6564d63..ab0f862 100644 --- a/man/plot.hce.Rd +++ b/man/plot.hce.Rd @@ -9,14 +9,15 @@ last_outcome = "C", arm_levels = c(active = "A", control = "P"), continuous_grid_spacing_x = 10, - trans = "identity", - density_plot_type = "default", + trans = c("identity", "log", "log10", "sqrt", "reverse")[1], + density_plot_type = c("default", "violin", "box", "scatter")[1], vline_type = NULL, fixed_followup_days = NULL, compute_win_odds = FALSE, step_types = "tte", last_type = "continuous", theme = "maraca", + lowerBetter = FALSE, continuous_outcome = lifecycle::deprecated(), ... ) @@ -38,8 +39,10 @@ be specified if you have labels different from \item{continuous_grid_spacing_x}{The spacing of the x grid to use for the continuous section of the plot.} -\item{trans}{the transformation to apply to the data before plotting. -The accepted values are the same that ggplot2::scale_x_continuous} +\item{trans}{the transformation to apply to the x-axis scale for the last +outcome. Possible values are "identity", "log" (only for continuous +endpoint), "log10" (only for continuous endpoint), "sqrt" (only for +continuous endpoint) and "reverse". The default value is "identity".} \item{density_plot_type}{The type of plot to use to represent the density. Accepts "default", "violin", "box" and "scatter".} @@ -76,6 +79,13 @@ For more details, check the vignette called "Maraca Plots - Themes and Styling". [companion vignette for package users](themes.html)} +\item{lowerBetter}{Flag for the final outcome variable, indicating if +lower values are considered better/advantageous. +This flag is need to make sure the win odds are +calculated correctly. +Default value is FALSE, meaning higher values +are considered advantageous.} + \item{continuous_outcome}{Deprecated and substituted by the more general 'last_outcome'. A single string containing the continuous outcome label.} diff --git a/man/plot.maraca.Rd b/man/plot.maraca.Rd index a05c92d..3e26618 100644 --- a/man/plot.maraca.Rd +++ b/man/plot.maraca.Rd @@ -7,8 +7,8 @@ \method{plot}{maraca}( x, continuous_grid_spacing_x = 10, - trans = "identity", - density_plot_type = "default", + trans = c("identity", "log", "log10", "sqrt", "reverse")[1], + density_plot_type = c("default", "violin", "box", "scatter")[1], vline_type = NULL, theme = "maraca", ... @@ -20,8 +20,10 @@ \item{continuous_grid_spacing_x}{The spacing of the x grid to use for the continuous section of the plot.} -\item{trans}{the transformation to apply to the data before plotting. -The accepted values are the same that ggplot2::scale_x_continuous} +\item{trans}{the transformation to apply to the x-axis scale for the last +outcome. Possible values are "identity", "log" (only for continuous +endpoint), "log10" (only for continuous endpoint), "sqrt" (only for +continuous endpoint) and "reverse". The default value is "identity".} \item{density_plot_type}{The type of plot to use to represent the density. Accepts "default", "violin", "box" and "scatter".} diff --git a/man/plot_maraca.Rd b/man/plot_maraca.Rd index d48954c..207c820 100644 --- a/man/plot_maraca.Rd +++ b/man/plot_maraca.Rd @@ -7,8 +7,8 @@ plot_maraca( obj, continuous_grid_spacing_x = NULL, - trans = "identity", - density_plot_type = "default", + trans = c("identity", "log", "log10", "sqrt", "reverse")[1], + density_plot_type = c("default", "violin", "box", "scatter")[1], vline_type = NULL, theme = "maraca" ) @@ -19,8 +19,10 @@ plot_maraca( \item{continuous_grid_spacing_x}{The spacing of the x grid to use for the continuous section of the plot.} -\item{trans}{the transformation to apply to the data before plotting. -The accepted values are the same that ggplot2::scale_x_continuous} +\item{trans}{the transformation to apply to the x-axis scale for the last +outcome. Possible values are "identity", "log" (only for continuous +endpoint), "log10" (only for continuous endpoint), "sqrt" (only for +continuous endpoint) and "reverse". The default value is "identity".} \item{density_plot_type}{which type of plot to display in the continuous part of the plot. Options are "default", "violin", "box", "scatter".} diff --git a/tests/testthat/test_maraca.R b/tests/testthat/test_maraca.R index b6900d0..c1a118d 100644 --- a/tests/testthat/test_maraca.R +++ b/tests/testthat/test_maraca.R @@ -517,7 +517,8 @@ test_that("winOddsData", { ) win_odds_list <- .compute_win_odds(data, arm_levels, - step_outcomes, last_outcome) + step_outcomes, last_outcome, + lowerBetter = FALSE) win_odds <- win_odds_list[["win_odds"]] expect_equal(class(win_odds), "numeric") @@ -1095,8 +1096,11 @@ test_that("gridSpacing", { test_that("scaleTransform", { file <- fixture_path("hce_scenario_c.csv") args <- .maraca_args(file) + dat <- args$data + dat[dat$GROUP == "Continuous outcome", "AVAL0"] <- + dat[dat$GROUP == "Continuous outcome", "AVAL0"] + 50 mar <- maraca( - args$data, + dat, args$step_outcomes, args$last_outcome, args$arm_levels,