Nothing
#' Minimal Node Size Pruning
#'
#' Computes optimal minimal node size of a discrete survival tree from a given vector
#' of possible node sizes by cross-validation. Laplace-smoothing can be applied to the
#' estimated hazards.
#'
#' @param formulaVariable Model formula for tree fitting (class "formula") of the form "~ x1 + x2 + ..." without response.
#' @param dataShort Discrete survival data in short format for which a survival tree is
#' to be fitted (class "data.frame").
#' @param treetype Type of tree to be fitted (class "character"). Possible values are "rpart" or "ranger". The default
#' is to fit an rpart tree; when "ranger" is chosen, a ranger forest with a single tree is fitted.
#' @param splitruleranger String specifying the splitting rule of the ranger tree (class "character").
#' Possible values are either "gini", "extratrees" or "hellinger". Default is "hellinger".
#' @param sizes Vector of different node sizes to try (class "integer").
#' Values should be non-negative.
#' @param indexList List of data partitioning indices for cross-validation (class "list").
#' Each element represents the test indices of one fold (class "integer").
#' @param timeColumn Character giving the column name of the observed times in
#' the \emph{data} argument (class "character").
#' @param eventColumn Character giving the column name of the event indicator in
#' the \emph{data} argument (class "character").
#' @param alpha Parameter for laplace-smoothing. A value of 0 corresponds to
#' no laplace-smoothing (class "numeric").
#' @param logOut Logical value (class "logical"). If the argument is set to TRUE,
#' then computation progress will be written to console.
#' @param ... Additional arguments to the estimation function. It is either "rpart"
#' or "ranger" (see argument \emph{treetype}).
#' @details Computes the out-of-sample log likelihood for all data partitionings
#' for each node size in \emph{sizes} and returns the node size for which the log
#' likelihood was minimal. Also returns an rpart tree with the optimal minimal
#' node size using the entire data set.
#' @note Note that depending on argument \emph{treetype} some arguments are fixed
#' and can not be changed:
#' \itemize{
#' \item \emph{treetype}="rpart": formula, data, method, minbucket
#' \item \emph{treetype}="ranger": formula, data, num.trees, mtry,
#' classification, splitrule, replace, sample.fraction, min.node.size
#' }
#' @return A list containing the two items
#' \itemize{
#' \item OptimNodeSize - Node size with lowest out-of-sample log-likelihood
#' \item OptimTree - A tree object with type corresponding to \emph{treetype} argument with the optimal minimal node size
#' }
#' @examples
#' library(pec)
#' library(caret)
#' data(cost)
#'
#' # Take subsample and convert time to years
#' cost$time <- ceiling(cost$time / 365)
#' costSub <- cost[1:50, ]
#'
#' # Specify column names for data augmentation
#' timeColumn <- "time"
#' eventColumn <- "status"
#'
#' # Create cross validation sets
#' # Stratified by event and time distribution
#' indexList <- createFolds(factor(paste(costSub$status,
#' costSub$time, sep="_")), k = 5)
#'
#' # Perform minimal node size pruning
#' formula1 <- ~ timeInt + prevStroke + age + sex
#' sizes <- 1:10
#' optiTree <- minNodePruning(formula1, costSub, treetype = "rpart", sizes = sizes,
#' indexList = indexList, timeColumn = timeColumn, eventColumn = eventColumn,
#' alpha = 1, logOut = TRUE)
#' plot(optiTree)
#'
#' @export minNodePruning
minNodePruning <- function(formulaVariable, dataShort, treetype = "rpart", splitruleranger = "hellinger", sizes, indexList, timeColumn,
eventColumn, alpha = 1, logOut = FALSE, ...)
{
# Construct formula
constructFormula <- formula(paste("y ~",
paste(attr(terms(formulaVariable),"term.labels"),
collapse=" + "), sep = " "))
#inputchecks
if (!treetype %in% c("rpart", "ranger"))
{
stop("treetype must be either \"rpart\" or \"ranger\".")
}
mean_total_llh <- rep(NA, length(sizes))
for (iNode in 1:length(sizes))
{
total_llh <- rep(NA, length(indexList))
for (iTrainIndex in 1:length(indexList))
{
dataTrain <- dataShort[-indexList[[iTrainIndex]],]
dataTest <- dataShort[indexList[[iTrainIndex]],]
dataTrainLong <- dataLong(dataTrain, timeColumn, eventColumn)
dataTestLong <- dataLong(dataTest, timeColumn, eventColumn)
if(treetype == "ranger")
{
tree <- ranger(constructFormula, dataTrainLong, num.trees = 1, mtry = length(attr(terms(constructFormula), "term.labels")),
classification = TRUE, splitrule = splitruleranger, replace = FALSE,
sample.fraction = 1, min.node.size = sizes[iNode])
test_hazards <- survTreeLaplaceHazard(tree, dataTestLong, alpha, dataTrainLong)
} else
{
tree <- rpart(constructFormula, dataTrainLong, method = "class", minbucket = sizes[iNode])
test_hazards <- survTreeLaplaceHazard(tree, dataTestLong, alpha)
}
lh <- test_hazards[dataTestLong$y*nrow(test_hazards) + c(1:nrow(test_hazards))]
llh <- -log(lh)
total_llh[iTrainIndex] <- sum(llh)
}
mean_total_llh[iNode] <- mean(total_llh)
if(logOut)
{
cat('\r',iNode/length(sizes)*100, "% finished")
flush.console()
}
}
selectSize1 <- max(sizes[mean_total_llh==min(mean_total_llh)])
optimalNodeSize <- sizes[sizes==selectSize1]
attr(optimalNodeSize,"llh") <- data.frame(sizes, mean_total_llh)
dataLong <- dataLong(dataShort, timeColumn, eventColumn)
if(treetype == "ranger")
{
optimalTree <- ranger(constructFormula, dataLong, num.trees = 1, mtry = length(attr(terms(constructFormula), "term.labels")),
classification = TRUE, splitrule = "hellinger", replace = FALSE,
sample.fraction = 1, min.node.size = optimalNodeSize,
...)
} else
{
optimalTree <- rpart(constructFormula, dataLong, method = "class",
minbucket = optimalNodeSize, ...)
}
RES <- list("OptimNodeSize" = optimalNodeSize,
"OptimTree" = optimalTree)
class(RES) <- "discSurvMinNodeSizePrune"
return(RES)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.