diff --git a/.Rbuildignore b/.Rbuildignore
index 79cee3a..801080a 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -17,4 +17,5 @@ copilot-instructions.md
^doc$
^Meta$
^icon$
+^examples$
^CRAN-SUBMISSION$
diff --git a/NAMESPACE b/NAMESPACE
index a6cb523..72528df 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -16,6 +16,7 @@ export(br_get_x)
export(br_get_x2)
export(br_get_y)
export(br_pipeline)
+export(br_predict)
export(br_rename_models)
export(br_run)
export(br_set_model)
@@ -29,6 +30,7 @@ export(br_show_forest_ggstats)
export(br_show_forest_ggstatsplot)
export(br_show_residuals)
export(br_show_risk_network)
+export(br_show_survival_curves)
export(br_show_table)
export(br_show_table_gt)
export(breg)
@@ -67,7 +69,13 @@ importFrom(rlang,is_string)
importFrom(rlang,is_vector)
importFrom(rlang,set_names)
importFrom(stats,cor)
+importFrom(stats,pchisq)
+importFrom(stats,predict)
+importFrom(stats,quantile)
+importFrom(survival,Surv)
importFrom(survival,coxph)
+importFrom(survival,survdiff)
+importFrom(survival,survfit)
importFrom(utils,combn)
importFrom(utils,packageDescription)
importFrom(utils,packageVersion)
diff --git a/R/00-bregr-package.R b/R/00-bregr-package.R
index 5890802..898e3aa 100644
--- a/R/00-bregr-package.R
+++ b/R/00-bregr-package.R
@@ -5,11 +5,11 @@
#' @import vctrs
#' @import cli
#' @importFrom mirai .progress
-#' @importFrom survival coxph
+#' @importFrom survival Surv survdiff survfit coxph
#' @importFrom lifecycle deprecated
#' @importFrom rlang .data .env
#' @importFrom utils combn packageDescription packageVersion
-#' @importFrom stats cor
+#' @importFrom stats cor pchisq quantile predict
#' @rawNamespace if (getRversion() < "4.3.0") importFrom("S7", "@")
## usethis namespace: end
NULL
diff --git a/R/02-pipeline.R b/R/02-pipeline.R
index ee3b88c..3fb5702 100644
--- a/R/02-pipeline.R
+++ b/R/02-pipeline.R
@@ -99,18 +99,19 @@
#' # 3. Customized model -----------
#' dt <- data.frame(x = rnorm(100))
#' dt$y <- rpois(100, exp(1 + dt$x))
+#' \donttest{
#' m5 <- breg(dt) |>
#' br_set_y("y") |>
#' br_set_x("x") |>
#' br_set_model(method = 'quasi(variance = "mu", link = "log")') |>
#' br_run()
+#' }
#'
#' @testexamples
#' assert_breg_obj(m)
#' assert_breg_obj(m2)
#' assert_breg_obj(m3)
#' assert_breg_obj(m4)
-#' assert_breg_obj(m5)
#' @seealso [accessors] for accessing `breg` object properties.
NULL
@@ -120,10 +121,9 @@ NULL
br_pipeline <- function(
data, y, x, method, x2 = NULL,
group_by = NULL,
- n_workers = 1L, run_parallel = 1L,
+ n_workers = 1L, run_parallel = lifecycle::deprecated(),
model_args = list(),
run_args = list()) {
-
if (lifecycle::is_present(run_parallel)) {
lifecycle::deprecate_warn("1.1.0", "bregr::br_run(run_parallel = )", "bregr::br_run(n_workers = )")
n_workers <- run_parallel
diff --git a/R/03-accessors.R b/R/03-accessors.R
index 54e0f09..6187fe3 100644
--- a/R/03-accessors.R
+++ b/R/03-accessors.R
@@ -21,6 +21,7 @@
#' - `br_get_results()` returns modeling result `data.frame`.
#'
#' @name accessors
+#' @family accessors
#' @seealso [pipeline] for building `breg` objects.
#' @examples
#' m <- br_pipeline(mtcars,
@@ -188,3 +189,83 @@ br_get_results <- function(obj, tidy = FALSE, ...) {
}
dplyr::filter(results, ...)
}
+
+#' Predict method for breg objects
+#'
+#' @description
+#' `r lifecycle::badge('experimental')`
+#'
+#' Generate predictions from fitted models in a `breg` object.
+#' For Cox regression models, returns linear predictors (log relative hazard).
+#' For other models, returns predicted values.
+#'
+#' @param obj A `breg` object with fitted models.
+#' @param newdata Optional data frame for predictions. If NULL, uses original data.
+#' @param idx Model index, an integer or string.
+#' @param type Type of prediction. For Cox models: "lp" (linear predictor, default)
+#' or "risk" (relative risk). For other models: "response" (default) or "link".
+#' @returns Typically, a numeric vector of predictions.
+#' @export
+#' @family accessors
+#' @examples
+#' # Cox regression example
+#' if (requireNamespace("survival", quietly = TRUE)) {
+#' lung <- survival::lung |> dplyr::filter(ph.ecog != 3)
+#' mds <- br_pipeline(
+#' lung,
+#' y = c("time", "status"),
+#' x = c("age", "ph.ecog"),
+#' x2 = "sex",
+#' method = "coxph"
+#' )
+#' scores <- br_predict(mds)
+#' head(scores)
+#' }
+br_predict <- function(obj, newdata = NULL, idx = NULL, type = NULL) {
+ assert_breg_obj_with_results(obj)
+
+ # Get the model to use
+ if (is.null(idx)) {
+ cli::cli_inform("{.arg idx} not set, use the first model")
+ idx <- 1
+ } else {
+ if (length(idx) != 1) {
+ cli::cli_abort("please specify one model")
+ }
+ }
+ model <- br_get_models(obj, idx)
+
+ # Get data for prediction
+ if (is.null(newdata)) {
+ newdata <- br_get_data(obj)
+ }
+
+ # Determine prediction type
+ model_class <- class(model)[1]
+ if (is.null(type)) {
+ if (model_class == "coxph") {
+ # https://www.rdocumentation.org/packages/survival/versions/3.8-3/topics/predict.coxph
+ type <- "lp" # linear predictor (log relative hazard)
+ } else {
+ type <- "response" # predicted response
+ }
+ cli::cli_inform("{.arg type} is not specified, use {type} for the model")
+ }
+
+ # Generate predictions
+ tryCatch(
+ {
+ predictions <- predict(model, newdata = newdata, type = type)
+
+ # Handle missing values
+ if (any(is.na(predictions))) {
+ cli::cli_warn("Some predictions are NA, consider checking your data for missing values")
+ }
+
+ predictions
+ },
+ error = function(e) {
+ cli::cli_abort("Failed to generate predictions: {e$message}")
+ }
+ )
+}
diff --git a/R/04-show.R b/R/04-show.R
index f943b7c..1dfc86c 100644
--- a/R/04-show.R
+++ b/R/04-show.R
@@ -527,6 +527,174 @@ br_show_table_gt <- function(
t
}
+#' Show survival curves based on model scores
+#'
+#' @description
+#' `r lifecycle::badge('experimental')`
+#'
+#' Generate survival curves by grouping observations based on model prediction scores.
+#' This function is specifically designed for Cox regression models and creates
+#' survival curves comparing different risk groups.
+#'
+#' @param breg A `breg` object with fitted Cox regression models.
+#' @param idx Index or name of the model to use for prediction.
+#' If NULL, uses the first model.
+#' @param n_groups Number of groups to create based on score quantiles. Default is 3.
+#' @param group_labels Custom labels for the groups. If NULL, uses "Low", "Medium", "High"
+#' for 3 groups or "Q1", "Q2", etc. for other numbers.
+#' @param title Plot title. If NULL, generates automatic title.
+#' @param subtitle Plot subtitle.
+#' @returns A ggplot2 object showing survival curves.
+#' @export
+#' @family br_show
+#' @examples
+#' \donttest{
+#' # Cox regression example with survival curves
+#' if (requireNamespace("survival", quietly = TRUE)) {
+#' lung <- survival::lung |> dplyr::filter(ph.ecog != 3)
+#' mds <- br_pipeline(
+#' lung,
+#' y = c("time", "status"),
+#' x = c("age", "ph.ecog"),
+#' x2 = "sex",
+#' method = "coxph"
+#' )
+#' p <- br_show_survival_curves(mds)
+#' print(p)
+#' }
+#' }
+br_show_survival_curves <- function(breg,
+ idx = NULL,
+ n_groups = 3,
+ group_labels = NULL,
+ title = NULL,
+ subtitle = NULL) {
+ assert_breg_obj_with_results(breg)
+
+ # Get the model to use
+ if (is.null(idx)) {
+ cli::cli_inform("{.arg idx} not set, use the first model")
+ idx <- 1
+ } else {
+ if (length(idx) != 1) {
+ cli::cli_abort("please specify one model")
+ }
+ }
+ model <- br_get_models(breg, idx)
+
+ # Check if we have survival models
+ if (!inherits(model, "coxph")) {
+ cli::cli_abort("survival curves are only supported for Cox regression models (coxph)")
+ }
+
+ # Get predictions (risk scores)
+ scores <- br_predict(breg, idx = idx, type = "lp")
+ data <- br_get_data(breg)
+
+ # Get survival variables
+ y_vars <- br_get_y(breg)
+ if (length(y_vars) != 2) {
+ cli::cli_abort("Expected 2 survival variables (time, status), got {length(y_vars)}")
+ }
+
+ time_var <- y_vars[1]
+ status_var <- y_vars[2]
+
+ # Create score groups
+ score_quantiles <- quantile(scores, probs = seq(0, 1, length.out = n_groups + 1), na.rm = TRUE)
+
+ # Handle case where scores have little variation
+ if (length(unique(score_quantiles)) <= 2) {
+ cli::cli_warn("Score values have limited variation, grouping may not be meaningful")
+ }
+
+ score_groups <- cut(scores,
+ breaks = score_quantiles,
+ include.lowest = TRUE,
+ labels = FALSE
+ )
+
+ # Create group labels
+ if (is.null(group_labels)) {
+ if (n_groups == 3) {
+ group_labels <- c("Low Risk", "Medium Risk", "High Risk")
+ } else if (n_groups == 2) {
+ group_labels <- c("Low Risk", "High Risk")
+ } else {
+ group_labels <- paste0("Q", 1:n_groups)
+ }
+ } else if (length(group_labels) != n_groups) {
+ cli::cli_abort("Length of group_labels ({length(group_labels)}) must match n_groups ({n_groups})")
+ }
+
+ # Prepare data for survival analysis
+ surv_data <- data |>
+ dplyr::mutate(
+ .score = scores,
+ .score_group = factor(score_groups, labels = group_labels),
+ .time = .data[[time_var]],
+ .status = .data[[status_var]]
+ ) |>
+ dplyr::filter(!is.na(.data$.score_group))
+
+ # Create survival object
+ surv_obj <- survival::Surv(surv_data$.time, surv_data$.status)
+
+ # Fit Kaplan-Meier curves for each group
+ km_fit <- survival::survfit(surv_obj ~ .score_group, data = surv_data)
+
+ # Create survival curve data for plotting
+ surv_summary <- summary(km_fit)
+
+ plot_data <- data.frame(
+ time = surv_summary$time,
+ surv = surv_summary$surv,
+ group = surv_summary$strata,
+ upper = surv_summary$upper,
+ lower = surv_summary$lower
+ )
+
+ # Clean group names
+ plot_data$group <- gsub(".*=", "", plot_data$group)
+
+ # Create the plot
+ if (is.null(title)) {
+ focal_var <- names(br_get_models(breg))[idx %||% 1]
+ title <- paste("Survival Curves by", focal_var, "Model Score")
+ }
+
+ p <- ggplot2::ggplot(plot_data, ggplot2::aes(x = .data$time, y = .data$surv, color = .data$group)) +
+ ggplot2::geom_step(linewidth = 1) +
+ ggplot2::geom_ribbon(ggplot2::aes(ymin = .data$lower, ymax = .data$upper, fill = .data$group),
+ alpha = 0.3, color = NA
+ ) +
+ ggplot2::scale_y_continuous(limits = c(0, 1), labels = function(x) paste0(x * 100, "%")) +
+ ggplot2::labs(
+ title = title,
+ subtitle = subtitle,
+ x = "Time",
+ y = "Survival Probability",
+ color = "Risk Group",
+ fill = "Risk Group"
+ ) +
+ ggplot2::theme_minimal() +
+ ggplot2::theme(
+ legend.position = "bottom",
+ plot.title = ggplot2::element_text(hjust = 0.5),
+ plot.subtitle = ggplot2::element_text(hjust = 0.5)
+ )
+
+ # Add log-rank test p-value if requested
+ if (n_groups > 1) {
+ logrank_test <- survival::survdiff(surv_obj ~ .score_group, data = surv_data)
+ p_value <- pchisq(logrank_test$chisq, df = length(logrank_test$n) - 1, lower.tail = FALSE)
+
+ p <- p + ggplot2::labs(caption = paste("Log-rank test p-value:", format.pval(p_value, digits = 3)))
+ }
+
+ return(p)
+}
+
#' Show residuals vs fitted plot for regression models
#'
#' @description
diff --git a/README.Rmd b/README.Rmd
index 2bae063..f262d4d 100644
--- a/README.Rmd
+++ b/README.Rmd
@@ -113,7 +113,7 @@ mds <- br_pipeline(
Run in parallel:
-```{r}
+```{r warning=FALSE}
mds_p <- br_pipeline(
lung,
y = c("time", "status"),
@@ -183,6 +183,25 @@ mds2 <- br_pipeline(
br_show_risk_network(mds2)
```
+#### Model Score Prediction and Survival Curves
+
+For Cox-PH models, you can generate model predictions (risk scores) and create survival curves grouped by these scores:
+
+```{r}
+# Generate model predictions
+scores <- br_predict(mds2, idx = "ph.ecog")
+head(scores)
+```
+
+```{r dpi=150, fig.height=6}
+# Create survival curves based on model scores
+br_show_survival_curves(
+ mds2,
+ idx = "ph.ecog",
+ n_groups = 3,
+ title = "Survival Curves by 'ph.ecog' Model Risk Score"
+)
+```
### Table
diff --git a/README.md b/README.md
index 1dd85b4..2292e49 100644
--- a/README.md
+++ b/README.md
@@ -136,8 +136,10 @@ mds_p <- br_pipeline(
method = "coxph",
n_workers = 3
)
-#> Warning: running in parallel is typically not recommended for small number (<100) of focal terms
#> exponentiate estimates of model(s) constructed from coxph method at default
+#> ■■■■■■■ 20% | ETA: 6s
+#> ■■■■■■■■■■■■■■■■■■■ 60% | ETA: 7s
+#>
```
``` r
@@ -328,6 +330,36 @@ br_show_risk_network(mds2)
+#### Model Score Prediction and Survival Curves
+
+For Cox-PH models, you can generate model predictions (risk scores) and
+create survival curves grouped by these scores:
+
+``` r
+# Generate model predictions
+scores <- br_predict(mds2, idx = "ph.ecog")
+#> `type` is not specified, use lp for the model
+#> Warning: Some predictions are NA, consider checking your data for missing
+#> values
+head(scores)
+#> 1 2 3 4 5 6
+#> 0.3692998 -0.1608293 -0.2936304 0.1811648 -0.2493634 0.3692998
+```
+
+``` r
+# Create survival curves based on model scores
+br_show_survival_curves(
+ mds2,
+ idx = "ph.ecog",
+ n_groups = 3,
+ title = "Survival Curves by 'ph.ecog' Model Risk Score"
+)
+#> Warning: Some predictions are NA, consider checking your data for missing
+#> values
+```
+
+
+
### Table
Show tidy table result as pretty table:
@@ -394,12 +426,12 @@ site](https://wanglabcsu.github.io/bregr/).
``` r
covr::package_coverage()
-#> bregr Coverage: 77.37%
-#> R/98-utils.R: 37.18%
-#> R/02-pipeline.R: 78.01%
-#> R/04-show.R: 78.45%
+#> bregr Coverage: 76.26%
+#> R/98-utils.R: 51.14%
+#> R/03-accessors.R: 72.50%
+#> R/04-show.R: 75.31%
+#> R/02-pipeline.R: 76.32%
#> R/06-avail.R: 78.57%
-#> R/03-accessors.R: 80.00%
#> R/01-class.R: 90.70%
#> R/99-zzz.R: 90.91%
#> R/05-polar.R: 95.19%
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 24079df..bd3282f 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -32,6 +32,8 @@ reference:
- title: Model Diagnostics and Use
desc: Inspect and visualize models for diagnostic purposes, and enable effective model utilization.
contents:
+ - br_predict
+ - br_show_survival_curves
- br_show_fitted_line
- br_show_fitted_line_2d
- br_show_residuals
diff --git a/man/accessors.Rd b/man/accessors.Rd
index 9a34230..78e018b 100644
--- a/man/accessors.Rd
+++ b/man/accessors.Rd
@@ -104,4 +104,8 @@ br_get_results(m, tidy = TRUE, term == "cyl")
}
\seealso{
\link{pipeline} for building \code{breg} objects.
+
+Other accessors:
+\code{\link{br_predict}()}
}
+\concept{accessors}
diff --git a/man/br_predict.Rd b/man/br_predict.Rd
new file mode 100644
index 0000000..6442f3d
--- /dev/null
+++ b/man/br_predict.Rd
@@ -0,0 +1,48 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/03-accessors.R
+\name{br_predict}
+\alias{br_predict}
+\title{Predict method for breg objects}
+\usage{
+br_predict(obj, newdata = NULL, idx = NULL, type = NULL)
+}
+\arguments{
+\item{obj}{A \code{breg} object with fitted models.}
+
+\item{newdata}{Optional data frame for predictions. If NULL, uses original data.}
+
+\item{idx}{Model index, an integer or string.}
+
+\item{type}{Type of prediction. For Cox models: "lp" (linear predictor, default)
+or "risk" (relative risk). For other models: "response" (default) or "link".}
+}
+\value{
+Typically, a numeric vector of predictions.
+}
+\description{
+\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
+
+Generate predictions from fitted models in a \code{breg} object.
+For Cox regression models, returns linear predictors (log relative hazard).
+For other models, returns predicted values.
+}
+\examples{
+# Cox regression example
+if (requireNamespace("survival", quietly = TRUE)) {
+ lung <- survival::lung |> dplyr::filter(ph.ecog != 3)
+ mds <- br_pipeline(
+ lung,
+ y = c("time", "status"),
+ x = c("age", "ph.ecog"),
+ x2 = "sex",
+ method = "coxph"
+ )
+ scores <- br_predict(mds)
+ head(scores)
+}
+}
+\seealso{
+Other accessors:
+\code{\link{accessors}}
+}
+\concept{accessors}
diff --git a/man/br_show_fitted_line.Rd b/man/br_show_fitted_line.Rd
index c7fae81..f7a9abc 100644
--- a/man/br_show_fitted_line.Rd
+++ b/man/br_show_fitted_line.Rd
@@ -47,6 +47,7 @@ Other br_show:
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_residuals}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()},
\code{\link{br_show_table_gt}()}
}
diff --git a/man/br_show_fitted_line_2d.Rd b/man/br_show_fitted_line_2d.Rd
index 9c5d3f6..d9bbbc5 100644
--- a/man/br_show_fitted_line_2d.Rd
+++ b/man/br_show_fitted_line_2d.Rd
@@ -44,6 +44,7 @@ Other br_show:
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_residuals}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()},
\code{\link{br_show_table_gt}()}
}
diff --git a/man/br_show_forest.Rd b/man/br_show_forest.Rd
index acf8dae..e50a184 100644
--- a/man/br_show_forest.Rd
+++ b/man/br_show_forest.Rd
@@ -73,6 +73,7 @@ Other br_show:
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_residuals}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()},
\code{\link{br_show_table_gt}()}
}
diff --git a/man/br_show_forest_ggstats.Rd b/man/br_show_forest_ggstats.Rd
index 1fe9296..c8014d5 100644
--- a/man/br_show_forest_ggstats.Rd
+++ b/man/br_show_forest_ggstats.Rd
@@ -41,6 +41,7 @@ Other br_show:
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_residuals}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()},
\code{\link{br_show_table_gt}()}
}
diff --git a/man/br_show_forest_ggstatsplot.Rd b/man/br_show_forest_ggstatsplot.Rd
index ab56eba..66d139b 100644
--- a/man/br_show_forest_ggstatsplot.Rd
+++ b/man/br_show_forest_ggstatsplot.Rd
@@ -43,6 +43,7 @@ Other br_show:
\code{\link{br_show_forest_ggstats}()},
\code{\link{br_show_residuals}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()},
\code{\link{br_show_table_gt}()}
}
diff --git a/man/br_show_residuals.Rd b/man/br_show_residuals.Rd
index 7ee5699..fe54d0e 100644
--- a/man/br_show_residuals.Rd
+++ b/man/br_show_residuals.Rd
@@ -56,6 +56,7 @@ Other br_show:
\code{\link{br_show_forest_ggstats}()},
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()},
\code{\link{br_show_table_gt}()}
}
diff --git a/man/br_show_risk_network.Rd b/man/br_show_risk_network.Rd
index ee98828..f1af6df 100644
--- a/man/br_show_risk_network.Rd
+++ b/man/br_show_risk_network.Rd
@@ -38,6 +38,7 @@ Other br_show:
\code{\link{br_show_forest_ggstats}()},
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_residuals}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()},
\code{\link{br_show_table_gt}()}
diff --git a/man/br_show_survival_curves.Rd b/man/br_show_survival_curves.Rd
new file mode 100644
index 0000000..4eaed7c
--- /dev/null
+++ b/man/br_show_survival_curves.Rd
@@ -0,0 +1,70 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/04-show.R
+\name{br_show_survival_curves}
+\alias{br_show_survival_curves}
+\title{Show survival curves based on model scores}
+\usage{
+br_show_survival_curves(
+ breg,
+ idx = NULL,
+ n_groups = 3,
+ group_labels = NULL,
+ title = NULL,
+ subtitle = NULL
+)
+}
+\arguments{
+\item{breg}{A \code{breg} object with fitted Cox regression models.}
+
+\item{idx}{Index or name of the model to use for prediction.
+If NULL, uses the first model.}
+
+\item{n_groups}{Number of groups to create based on score quantiles. Default is 3.}
+
+\item{group_labels}{Custom labels for the groups. If NULL, uses "Low", "Medium", "High"
+for 3 groups or "Q1", "Q2", etc. for other numbers.}
+
+\item{title}{Plot title. If NULL, generates automatic title.}
+
+\item{subtitle}{Plot subtitle.}
+}
+\value{
+A ggplot2 object showing survival curves.
+}
+\description{
+\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
+
+Generate survival curves by grouping observations based on model prediction scores.
+This function is specifically designed for Cox regression models and creates
+survival curves comparing different risk groups.
+}
+\examples{
+\donttest{
+# Cox regression example with survival curves
+if (requireNamespace("survival", quietly = TRUE)) {
+ lung <- survival::lung |> dplyr::filter(ph.ecog != 3)
+ mds <- br_pipeline(
+ lung,
+ y = c("time", "status"),
+ x = c("age", "ph.ecog"),
+ x2 = "sex",
+ method = "coxph"
+ )
+ p <- br_show_survival_curves(mds)
+ print(p)
+}
+}
+}
+\seealso{
+Other br_show:
+\code{\link{br_show_fitted_line}()},
+\code{\link{br_show_fitted_line_2d}()},
+\code{\link{br_show_forest}()},
+\code{\link{br_show_forest_ggstats}()},
+\code{\link{br_show_forest_ggstatsplot}()},
+\code{\link{br_show_residuals}()},
+\code{\link{br_show_risk_network}()},
+\code{\link{br_show_table}()},
+\code{\link{br_show_table_gt}()}
+}
+\concept{br_show}
diff --git a/man/br_show_table.Rd b/man/br_show_table.Rd
index 44ae9cf..c989d3d 100644
--- a/man/br_show_table.Rd
+++ b/man/br_show_table.Rd
@@ -52,6 +52,7 @@ Other br_show:
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_residuals}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table_gt}()}
}
\concept{br_show}
diff --git a/man/br_show_table_gt.Rd b/man/br_show_table_gt.Rd
index 7be4542..d9fe4de 100644
--- a/man/br_show_table_gt.Rd
+++ b/man/br_show_table_gt.Rd
@@ -50,6 +50,7 @@ Other br_show:
\code{\link{br_show_forest_ggstatsplot}()},
\code{\link{br_show_residuals}()},
\code{\link{br_show_risk_network}()},
+\code{\link{br_show_survival_curves}()},
\code{\link{br_show_table}()}
}
\concept{br_show}
diff --git a/man/figures/README-unnamed-chunk-12-1.png b/man/figures/README-unnamed-chunk-12-1.png
new file mode 100644
index 0000000..c05d21f
Binary files /dev/null and b/man/figures/README-unnamed-chunk-12-1.png differ
diff --git a/man/pipeline.Rd b/man/pipeline.Rd
index 318b32a..e06fa0b 100644
--- a/man/pipeline.Rd
+++ b/man/pipeline.Rd
@@ -18,6 +18,7 @@ br_pipeline(
x2 = NULL,
group_by = NULL,
n_workers = 1L,
+ run_parallel = lifecycle::deprecated(),
model_args = list(),
run_args = list()
)
@@ -167,11 +168,13 @@ m4 <- br_pipeline(mtcars,
# 3. Customized model -----------
dt <- data.frame(x = rnorm(100))
dt$y <- rpois(100, exp(1 + dt$x))
+\donttest{
m5 <- breg(dt) |>
br_set_y("y") |>
br_set_x("x") |>
br_set_model(method = 'quasi(variance = "mu", link = "log")') |>
br_run()
+}
}
\seealso{
diff --git a/tests/testthat/test-predict-survival.R b/tests/testthat/test-predict-survival.R
new file mode 100644
index 0000000..9b37c0b
--- /dev/null
+++ b/tests/testthat/test-predict-survival.R
@@ -0,0 +1,99 @@
+test_that("br_predict works for Cox regression", {
+ skip_if_not_installed("survival")
+
+ # Create test data similar to survival::lung
+ set.seed(123)
+ n <- 50
+ test_data <- data.frame(
+ time = runif(n, 1, 1000),
+ status = rbinom(n, 1, 0.6),
+ age = rnorm(n, 60, 10),
+ sex = factor(sample(c("M", "F"), n, replace = TRUE))
+ )
+
+ # Create breg object with Cox regression
+ breg_obj <- br_pipeline(
+ test_data,
+ y = c("time", "status"),
+ x = "age",
+ x2 = "sex",
+ method = "coxph"
+ )
+
+ # Test predictions
+ predictions <- br_predict(breg_obj)
+
+ expect_true(is.numeric(predictions))
+ expect_equal(length(predictions), n)
+ expect_true(!any(is.na(predictions)))
+})
+
+test_that("br_show_survival_curves works for Cox regression", {
+ skip_if_not_installed("survival")
+ skip_if_not_installed("ggplot2")
+
+ # Create test data
+ set.seed(123)
+ n <- 100
+ test_data <- data.frame(
+ time = rexp(n, 0.01),
+ status = rbinom(n, 1, 0.7),
+ age = rnorm(n, 60, 10),
+ sex = factor(sample(c("M", "F"), n, replace = TRUE))
+ )
+
+ # Create breg object with Cox regression
+ breg_obj <- br_pipeline(
+ test_data,
+ y = c("time", "status"),
+ x = "age",
+ x2 = "sex",
+ method = "coxph"
+ )
+
+ # Test survival curves
+ p <- br_show_survival_curves(breg_obj, n_groups = 2)
+
+ expect_s3_class(p, "ggplot")
+})
+
+test_that("br_predict fails gracefully for non-coxph models", {
+ # Create test data for linear regression
+ test_data <- data.frame(
+ y = rnorm(50),
+ x = rnorm(50)
+ )
+
+ # Create breg object with linear regression
+ breg_obj <- br_pipeline(
+ test_data,
+ y = "y",
+ x = "x",
+ method = "gaussian"
+ )
+
+ # Test predictions work for non-coxph
+ predictions <- br_predict(breg_obj)
+ expect_true(is.numeric(predictions))
+})
+
+test_that("br_show_survival_curves fails for non-coxph models", {
+ # Create test data for linear regression
+ test_data <- data.frame(
+ y = rnorm(50),
+ x = rnorm(50)
+ )
+
+ # Create breg object with linear regression
+ breg_obj <- br_pipeline(
+ test_data,
+ y = "y",
+ x = "x",
+ method = "gaussian"
+ )
+
+ # Test that survival curves fail for non-coxph
+ expect_error(
+ br_show_survival_curves(breg_obj)
+ )
+})
diff --git a/tests/testthat/test-roxytest-testexamples-02-pipeline.R b/tests/testthat/test-roxytest-testexamples-02-pipeline.R
index 737be6c..9d37e84 100644
--- a/tests/testthat/test-roxytest-testexamples-02-pipeline.R
+++ b/tests/testthat/test-roxytest-testexamples-02-pipeline.R
@@ -2,7 +2,7 @@
# File R/"02-pipeline.R": @testexamples
-test_that("[unknown alias] @ L115", {
+test_that("[unknown alias] @ L116", {
library(bregr)
# 1. Pipeline -------------------------
@@ -47,16 +47,17 @@ test_that("[unknown alias] @ L115", {
# 3. Customized model -----------
dt <- data.frame(x = rnorm(100))
dt$y <- rpois(100, exp(1 + dt$x))
+
m5 <- breg(dt) |>
br_set_y("y") |>
br_set_x("x") |>
br_set_model(method = 'quasi(variance = "mu", link = "log")') |>
br_run()
+
assert_breg_obj(m)
assert_breg_obj(m2)
assert_breg_obj(m3)
assert_breg_obj(m4)
- assert_breg_obj(m5)
})
diff --git a/tests/testthat/test-roxytest-testexamples-03-accessors.R b/tests/testthat/test-roxytest-testexamples-03-accessors.R
index f189f23..ff50903 100644
--- a/tests/testthat/test-roxytest-testexamples-03-accessors.R
+++ b/tests/testthat/test-roxytest-testexamples-03-accessors.R
@@ -2,7 +2,7 @@
# File R/"03-accessors.R": @testexamples
-test_that("[unknown alias] @ L49", {
+test_that("[unknown alias] @ L50", {
m <- br_pipeline(mtcars,
y = "mpg",
diff --git a/tests/testthat/test-roxytest-testexamples-04-show.R b/tests/testthat/test-roxytest-testexamples-04-show.R
index 1a5e6ff..04728c6 100644
--- a/tests/testthat/test-roxytest-testexamples-04-show.R
+++ b/tests/testthat/test-roxytest-testexamples-04-show.R
@@ -120,7 +120,7 @@ test_that("Function br_show_table_gt() @ L500", {
})
-test_that("Function br_show_residuals() @ L569", {
+test_that("Function br_show_residuals() @ L737", {
m <- br_pipeline(mtcars,
y = "mpg",