diff --git a/DESCRIPTION b/DESCRIPTION index 8b78deb746..ee637dd486 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -54,7 +54,8 @@ Suggests: nestcolor (>= 0.1.1), rmarkdown, stringr, - testthat (>= 3.0) + testthat (>= 3.0), + vdiffr (>= 1.0.0) VignetteBuilder: knitr RdMacros: diff --git a/R/kaplan_meier_plot.R b/R/kaplan_meier_plot.R index a70550a4cd..ee12bd2475 100644 --- a/R/kaplan_meier_plot.R +++ b/R/kaplan_meier_plot.R @@ -27,6 +27,7 @@ #' @param xlab (`string`)\cr label of x-axis. #' @param ylab (`string`)\cr label of y-axis. #' @param ylim (`vector` of `numeric`)\cr vector of length 2 containing lower and upper limits for the y-axis. +#' If `NULL` (default), the minimum and maximum y-values displayed are used as limits. #' @param title (`string`)\cr title for plot. #' @param footnotes (`string`)\cr footnotes for plot. #' @param col (`character`)\cr lines colors. Length of a vector should be equal @@ -182,7 +183,7 @@ g_km <- function(df, xlab = "Days", yval = c("Survival", "Failure"), ylab = paste(yval, "Probability"), - ylim = c(0, 1), + ylim = NULL, title = NULL, footnotes = NULL, draw = TRUE, @@ -639,7 +640,7 @@ h_ggkm <- function(data, censor_show, xlab, ylab, - ylim = c(0, 1), + ylim = NULL, title, footnotes = NULL, max_time = NULL, @@ -652,6 +653,17 @@ h_ggkm <- function(data, ggtheme = nestcolor::theme_nest()) { checkmate::assert_numeric(lty, null.ok = TRUE) checkmate::assert_character(col, null.ok = TRUE) + + if (is.null(ylim)) { + if (!is.null(max_time)) { + y_lwr <- min(data[data$time < max_time, ][["estimate"]]) + y_upr <- max(data[data$time < max_time, ][["estimate"]]) + } else { + y_lwr <- min(data[["estimate"]]) + y_upr <- max(data[["estimate"]]) + } + ylim <- c(y_lwr, y_upr) + } checkmate::assert_numeric(ylim, finite = TRUE, any.missing = FALSE, len = 2, sorted = TRUE) # change estimates of survival to estimates of failure (1 - survival) diff --git a/man/g_km.Rd b/man/g_km.Rd index d7997f071b..92d088504d 100644 --- a/man/g_km.Rd +++ b/man/g_km.Rd @@ -19,7 +19,7 @@ g_km( xlab = "Days", yval = c("Survival", "Failure"), ylab = paste(yval, "Probability"), - ylim = c(0, 1), + ylim = NULL, title = NULL, footnotes = NULL, draw = TRUE, @@ -88,7 +88,8 @@ an optimal tick position on the x axis.} \item{ylab}{(\code{string})\cr label of y-axis.} -\item{ylim}{(\code{vector} of \code{numeric})\cr vector of length 2 containing lower and upper limits for the y-axis.} +\item{ylim}{(\code{vector} of \code{numeric})\cr vector of length 2 containing lower and upper limits for the y-axis. +If \code{NULL} (default), the minimum and maximum y-values displayed are used as limits.} \item{title}{(\code{string})\cr title for plot.} diff --git a/man/h_ggkm.Rd b/man/h_ggkm.Rd index 0a7e520b00..fef43250d3 100644 --- a/man/h_ggkm.Rd +++ b/man/h_ggkm.Rd @@ -11,7 +11,7 @@ h_ggkm( censor_show, xlab, ylab, - ylim = c(0, 1), + ylim = NULL, title, footnotes = NULL, max_time = NULL, @@ -39,7 +39,8 @@ an optimal tick position on the x axis.} \item{ylab}{(\code{string})\cr label of y-axis.} -\item{ylim}{(\code{vector} of \code{numeric})\cr vector of length 2 containing lower and upper limits for the y-axis.} +\item{ylim}{(\code{vector} of \code{numeric})\cr vector of length 2 containing lower and upper limits for the y-axis. +If \code{NULL} (default), the minimum and maximum y-values displayed are used as limits.} \item{title}{(\code{string})\cr title for plot.} diff --git a/tests/testthat/_snaps/g_km/g-km-crop-ylim.svg b/tests/testthat/_snaps/g_km/g-km-crop-ylim.svg new file mode 100644 index 0000000000..3eabe65fa0 --- /dev/null +++ b/tests/testthat/_snaps/g_km/g-km-crop-ylim.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.4 +0.6 +0.8 +1.0 + + + + + + + + + +0 +250 +500 +750 +1000 +Days +Survival Probability + + + + + + + +ARM A +ARM B +ARM C + + + +Censored + + diff --git a/tests/testthat/_snaps/g_km/g-km-custom-ylim.svg b/tests/testthat/_snaps/g_km/g-km-custom-ylim.svg new file mode 100644 index 0000000000..c9023ab0ea --- /dev/null +++ b/tests/testthat/_snaps/g_km/g-km-custom-ylim.svg @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.3 +0.4 +0.5 +0.6 +0.7 + + + + + + + + + + + +0 +1000 +2000 +3000 +4000 +5000 +Days +Survival Probability + + + + + + + +ARM A +ARM B +ARM C + + + +Censored + + diff --git a/tests/testthat/test-g_km.R b/tests/testthat/test-g_km.R index 90de269250..1f7ea7d9bd 100644 --- a/tests/testthat/test-g_km.R +++ b/tests/testthat/test-g_km.R @@ -52,3 +52,31 @@ testthat::test_that("g_km plot with < = > in group labels works", { testthat::expect_true(grid::is.grob(grob_tmp)) }) + +testthat::test_that("g_km ylim parameter works as expected", { + set.seed(123) + + df <- tern_ex_adtte %>% + dplyr::filter(PARAMCD == "OS") %>% + dplyr::mutate(is_event = CNSR == 0) + + variables <- list(tte = "AVAL", is_event = "is_event", arm = "ARMCD") + + g_km_crop_ylim <- g_km( + df = df, + variables = variables, + annot_surv_med = FALSE, + annot_at_risk = FALSE, + max_time = 1000 + ) + vdiffr::expect_doppelganger(title = "g_km_crop_ylim", fig = g_km_crop_ylim) + + g_km_custom_ylim <- g_km( + df = df, + variables = variables, + annot_surv_med = FALSE, + annot_at_risk = FALSE, + ylim = c(0.25, 0.75) + ) + vdiffr::expect_doppelganger(title = "g_km_custom_ylim", fig = g_km_custom_ylim) +})