diff --git a/NAMESPACE b/NAMESPACE index 23807b0b8..de8a03ef4 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -69,6 +69,7 @@ export(MeasureSurvUnoAUC) export(MeasureSurvUnoTNR) export(MeasureSurvUnoTPR) export(MeasureSurvXuR2) +export(PipeOpBreslow) export(PipeOpCrankCompositor) export(PipeOpDistrCompositor) export(PipeOpPredRegrSurv) diff --git a/R/PipeOpBreslow.R b/R/PipeOpBreslow.R index 189719475..af5dd36e8 100644 --- a/R/PipeOpBreslow.R +++ b/R/PipeOpBreslow.R @@ -1,14 +1,73 @@ #' @title PipeOpBreslow #' @name mlr_pipeops_compose_breslow_distr +#' @template param_pipelines #' @description -#' A short description... +#' Composes a survival distribution (`distr`) from the linear predictor +#' predictions (`lp`) of a given [LearnerSurv] generated during training and +#' prediction using the [breslow] estimator. +#' The input `learner` needs to be able to predict `lp` type of predictions (eg +#' a Cox-type of model). #' +#' @section Dictionary: +#' This [PipeOp][mlr3pipelines::PipeOp] can be instantiated via the +#' [Dictionary][mlr3misc::Dictionary] [mlr_pipeops][mlr3pipelines::mlr_pipeops] +#' or with the associated sugar function [po()][mlr3pipelines::po]: +#' ``` +#' PipeOpBreslow$new(learner) +#' mlr_pipeops$get("breslowcompose", learner) +#' po("breslowcompose", learner, overwrite = TRUE) +#' ``` +#' +#' @section Input and Output Channels: +#' [PipeOpBreslow] is like a [LearnerSurv]. +#' It has one input channel, named `input` that takes a [TaskSurv] during training +#' and another [TaskSurv] during prediction. +#' [PipeOpBreslow] has one output channel named `output`, producing `NULL` during +#' training and a [PredictionSurv] during prediction. +#' +#' @section State: +#' The `$state` slot stores the `times` and `status` survival target variables of +#' the train [TaskSurv] as well as the `lp` predictions on the train set. +#' +#' @section Parameters: +#' The parameters are: +#' * `overwrite` :: `logical(1)` \cr +#' If `FALSE` (default) then the compositor does nothing and returns the +#' input `learner`'s [PredictionSurv]. +#' If `TRUE` or in the case that the input `learner` doesn't have `distr` +#' predictions, then the `distr` is overwritten with the `distr` composed +#' from `lp` and the train set information using [breslow]. +#' This is useful for changing the prediction `distr` from one model form to +#' another. +#' @seealso [pipeline_distrcompositor] +#' @export +#' @family survival compositors +#' @examples +#' \dontrun{ +#' if (requireNamespace("mlr3pipelines", quietly = TRUE)) { +#' library(mlr3) +#' library(mlr3pipelines) +#' task = tsk("rats") +#' part = partition(task, ratio = 0.8) +#' train_task = task$clone()$filter(part$train) +#' test_task = task$clone()$filter(part$test) +#' +#' learner = lrn("surv.coxph") # learner with lp predictions +#' b = po("breslowcompose", learner = learner, overwrite = TRUE) +#' +#' b$train(list(train_task)) +#' p = b$predict(list(test_task))[[1L]] +#' } +#' } PipeOpBreslow = R6Class("PipeOpBreslow", inherit = mlr3pipelines::PipeOp, public = list( #' @description #' Creates a new instance of this [R6][R6::R6Class] class. - #' @param id description + #' @param learner ([LearnerSurv])\cr + #' Survival learner which must provide `lp`-type predictions + #' @param id (character(1))\cr + #' Identifier of the resulting object. initialize = function(learner, id = "po_breslow", param_vals = list(overwrite = FALSE)) { if ("lp" %nin% learner$predict_types) { stopf("Learner %s must provide lp predictions", learner$id) @@ -37,6 +96,8 @@ PipeOpBreslow = R6Class("PipeOpBreslow", ), active = list( + #' @field learner \cr + #' The input learner. learner = function(rhs) { assert_ro_binding(rhs) private$.learner @@ -86,8 +147,11 @@ PipeOpBreslow = R6Class("PipeOpBreslow", p = learner$predict(task) pv = self$param_set$get_values(tags = "predict") - if (is.null(pv$overwrite) || !pv$overwrite) { - #browser() + overwrite = pv$overwrite + + # If learner predicts `distr` and overwrite is FALSE don't use breslow + if ("distr" %in% learner$predict_types & !overwrite) { + browser() pred = list(p) } else { # missing lp diff --git a/man/mlr_pipeops_compose_breslow_distr.Rd b/man/mlr_pipeops_compose_breslow_distr.Rd new file mode 100644 index 000000000..d4242542e --- /dev/null +++ b/man/mlr_pipeops_compose_breslow_distr.Rd @@ -0,0 +1,156 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpBreslow.R +\name{mlr_pipeops_compose_breslow_distr} +\alias{mlr_pipeops_compose_breslow_distr} +\alias{PipeOpBreslow} +\title{PipeOpBreslow} +\description{ +Composes a survival distribution (\code{distr}) from the linear predictor +predictions (\code{lp}) of a given \link{LearnerSurv} generated during training and +prediction using the \link{breslow} estimator. +The input \code{learner} needs to be able to predict \code{lp} type of predictions (eg +a Cox-type of model). +} +\section{Dictionary}{ + +This \link[mlr3pipelines:PipeOp]{PipeOp} can be instantiated via the +\link[mlr3misc:Dictionary]{Dictionary} \link[mlr3pipelines:mlr_pipeops]{mlr_pipeops} +or with the associated sugar function \link[mlr3pipelines:po]{po()}: + +\if{html}{\out{