#' Print MachineShop Objects
#'
#' Print methods for objects defined in the \pkg{MachineShop} package.
#'
#' @name print
#' @rdname print-methods
#'
#' @param x object to print.
#' @param n integer number of models or data frame rows to show.
#' @param id logical indicating whether to show object identifiers.
#' @param data logical indicating whether to show model data.
#' @param ... arguments passed to other methods, including the one described
#' below.
#' \describe{
#' \item{\code{level} = 0}{current nesting level of the corresponding
#' object in recursive calls to \code{print}. The amount of information
#' displayed decreases and increases with positive and negative levels,
#' respectively.}
#' }
#'
NULL
setShowDefault <- function(signature) {
setMethod("show", signature, function(object) {
print(object)
invisible()
})
}
#' @rdname print-methods
#'
print.BinomialVariate <- function(
x, n = MachineShop::settings("print_max"), ...
) {
title(x, pad = FALSE, ...)
print_items(as(x, "matrix"), n = n)
invisible(x)
}
#' @rdname print-methods
#'
print.Calibration <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, ...)
print_items(as(x, "data.frame"), n = n)
invisible(x)
}
setShowDefault("Calibration")
print.ConfusionList <- function(
x, n = MachineShop::settings("print_max"), ...
) {
title(x, ...)
level <- nesting_level(...)
NextMethod(level = level + 1)
}
print.ConfusionMatrix <- function(x, ...) {
title(x, pad = FALSE, ...)
print(as(x, "table"))
invisible(x)
}
setShowDefault("ConfusionMatrix")
print.ConfusionSummary <- function(x, ...) {
acc <- x@accuracy
acc_se <- sqrt(acc * (1 - acc) / x@total)
print_fields(list(
"Number of responses: " = x@total,
"Accuracy (SE): " = paste0(format(acc), " (", format(acc_se), ")"),
"Majority class: " = x@majority,
"Kappa: " = x@kappa2
))
newline()
print(as(x, "matrix"))
invisible(x)
}
setShowDefault("ConfusionSummary")
#' @rdname print-methods
#'
print.DiscreteVariate <- function(
x, n = MachineShop::settings("print_max"), ...
) {
title(x, pad = FALSE, ...)
print_items(as(x, "numeric"), n = n)
print_fields(list("Range: " = c(x@min, x@max)))
invisible(x)
}
setShowDefault("DiscreteVariate")
print.EnsembleModel <- function(
x, n = MachineShop::settings("print_max"), id = FALSE, ...
) {
title(x, ...)
level <- nesting_level(...)
nextlevel <- level + 1
trained <- is_trained(x)
print_modelinfo(x, trained = trained, ...)
if (level < 1) {
hline(level)
print_train_label("Models:")
newline()
print(x@candidates, n = n, level = nextlevel, id = id)
hline(level)
print(x@params, n = n, level = nextlevel)
if (trained) {
hline(level)
print(x@steps, n = n, level = nextlevel)
}
} else if (level == 1) {
newline()
print_train_label("Models:")
print(x@candidates, n = n, level = nextlevel, id = id)
}
invisible(x)
}
#' @rdname print-methods
#'
print.ListOf <- function(x, n = MachineShop::settings("print_max"), ...) {
print_items(x, n = n, ...)
invisible(x)
}
setShowDefault("ListOf")
setShowDefault("MLControl")
#' @rdname print-methods
#'
print.MLControl <- function(x, n = MachineShop::settings("print_max"), ...) {
print_control(x, n = n, ...)
}
print.BootControl <- function(x, ...) {
fields <- list("Samples: " = x@samples)
NextMethod(fields = fields)
}
print.CVControl <- function(x, ...) {
fields <- list("Folds: " = x@folds, "Repeats: " = x@repeats)
NextMethod(fields = fields)
}
print.NullControl <- function(x, ...) {
title(x, ...)
print_fields(list("Label: " = x@label))
invisible(x)
}
print.OOBControl <- function(x, ...) {
fields <- list("Samples: " = x@samples)
NextMethod(fields = fields)
}
print.SplitControl <- function(x, ...) {
fields = list("Training proportion: " = x@prop)
NextMethod(fields = fields)
}
#' @rdname print-methods
#'
print.MLMetric <- function(x, ...) {
title(x, ...)
level <- nesting_level(...)
print_fields(list(
"Metric name: " = x@name,
"Label: " = x@label,
"Maximize: " = x@maximize
))
if (level < 1) {
info <- metricinfo(x)[[1]]
newline()
print_label("Arguments:")
print(info$arguments)
newline()
print_label("Types:")
print(info$response_types)
}
invisible(x)
}
setShowDefault("MLMetric")
#' @rdname print-methods
#'
print.MLModel <- function(
x, n = MachineShop::settings("print_max"), id = FALSE, ...
) {
title(x, ...)
level <- nesting_level(...)
trained <- is_trained(x)
print_modelinfo(x, trained = trained, id = id, ...)
if (level < 1) {
newline()
print_str(x@params, label = "Parameter{?s}:", n = n)
if (trained) {
newline()
print(x@steps, n = n, level = level + 1)
}
}
invisible(x)
}
setShowDefault("MLModel")
print.MLModelFit <- function(x, ...) {
print(unMLModelFit(x), ...)
invisible(x)
}
setShowDefault("MLModelFit")
#' @rdname print-methods
#'
print.MLModelFunction <- function(x, ...) {
title(x, ...)
level <- nesting_level(...)
print_modelinfo(x, ...)
if (level < 1) {
newline()
print_label("Arguments:")
print(args(x))
}
invisible(x)
}
setShowDefault("MLModelFunction")
print.MLOptimization <- function(
x, n = MachineShop::settings("print_max"), ...
) {
title(x, ...)
level <- nesting_level(...)
print_fields(list("Label: " = x@label))
if (level < 1) {
print_fields(list(
"Package{?s}: " = unname(x@packages),
"Monitor: " = x@monitor
), add_names = TRUE)
if (length(x@params)) print_str(x@params, label = "Parameter{?s}:", n = n)
}
invisible(x)
}
setShowDefault("MLOptimization")
#' @rdname print-methods
#'
print.ModelFrame <- function(
x, n = MachineShop::settings("print_max"), id = FALSE, data = TRUE, ...
) {
title(x, ...)
level <- nesting_level(...)
if (id) print_id(x)
label <- if (level < 2) style_label("Terms: ")
print_items(formula(x), n = n, label = label)
if (data) print_data(as(x, "data.frame"), n = n, level = level)
invisible(x)
}
setShowDefault("ModelFrame")
#' @rdname print-methods
#'
print.ModelRecipe <- function(
x, n = MachineShop::settings("print_max"), id = FALSE, data = TRUE, ...
) {
title(x, ...)
level <- nesting_level(...)
if (id) print_id(x)
tbl <- summary(x, original = TRUE)
print_fields(list(
"Outcome{?s}: " = tbl$variable[tbl$role == "outcome"],
"Predictor{?s}: " = tbl$variable[tbl$role == "predictor"]
), n = n)
if (level < 2) {
steps <- map("char", class1, x$steps)
step_label <- paste(if (is_trained(x)) "Trained" else "Untrained", "step")
if (id) {
steps <- structure(map("char", getElement, x$steps, "id"), names = steps)
step_label <- paste(step_label, "ID")
}
print_fields(
list(steps = steps), labels = c(steps = paste0(step_label, "{?s}: ")),
add_names = TRUE, n = n
)
}
if (level < 1) print_fields(list("Tuning grid: " = has_grid(x)))
if (data) print_data(as_tibble(as.data.frame(x)), n = n, level = level)
invisible(x)
}
setShowDefault("ModelRecipe")
#' @rdname print-methods
#'
print.ModelSpecification <- function(
x, n = MachineShop::settings("print_max"), id = FALSE, ...
) {
title(x, ...)
level <- nesting_level(...)
nextlevel <- level + 1
if (id) {
print_id(x)
newline()
}
show_all <- length(x@grid) && level < 1
print(x@input, n = n, level = nextlevel, id = show_all)
if (!is(x@model, "NullModel")) {
newline()
print(x@model, n = n, level = nextlevel, id = show_all)
}
if (show_all) {
newline()
heading("Grid", level = nextlevel)
print_items(x@grid, n = n)
newline()
print(x@params, n = n, level = nextlevel)
}
}
setShowDefault("ModelSpecification")
print.ModelTerms <- function(x, n = MachineShop::settings("print_max"), ...) {
print_items(formula(x), n = n)
invisible(x)
}
print.ParameterGrid <- function(x, ...) {
NextMethod()
newline()
print(as(x, "parameters"))
invisible(x)
}
setShowDefault("ParameterGrid")
print.ParsnipModel <- function(x, ...) {
x@params <- x@params$object$args
NextMethod()
}
#' @rdname print-methods
#'
print.Performance <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, ...)
level <- nesting_level(...)
dn <- dimnames(x)
print_fields(list("Metric{?s}: " = dn[[2]]))
if (length(dn) > 2) {
print_fields(list("Model{?s}: " = dn[[3]]), n = n)
}
newline()
print(x@control, level = level + 1)
invisible(x)
}
#' @rdname print-methods
#'
print.PerformanceCurve <- function(
x, n = MachineShop::settings("print_max"), ...
) {
title(x, ...)
level <- nesting_level(...)
xy_labels <- c(x@metrics$x@label, x@metrics$y@label)
print_fields(list("Metrics: " = paste(c("x", "y"), "=", xy_labels)))
newline()
print_items(as(x, "data.frame"), n = n)
if (!is(x@control, "NullControl")) {
newline()
print(x@control, level = level + 1)
}
invisible(x)
}
setShowDefault("PerformanceCurve")
print.PerformanceDiffTest <- function(x, ...) {
title(x, ...)
print_fields(list(
"Upper diagonal: " = "mean differences (Model1 - Model2)",
"Lower diagonal: " = "p-values",
"P-value adjustment method: " = x@adjust
))
newline()
print(as(x, "array"))
invisible(x)
}
print.RandomGridSearch <- function(x, ...) {
NextMethod()
print_fields(list("Samples: " = x@size))
invisible(x)
}
#' @rdname print-methods
#'
print.RecipeGrid <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, ...)
print_items(as(x, "tbl_df"), n = n)
invisible(x)
}
setShowDefault("RecipeGrid")
#' @rdname print-methods
#'
print.Resample <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, ...)
level <- nesting_level(...)
print_fields(list("Model{?s}: " = levels(x$Model)), n = n)
if (level >= 1) {
print_fields(list(
"Grouping variable: " = names(x@vars[["Grouping"]]),
"Stratification variable: " = names(x@vars[["Stratification"]])
))
} else if (length(x@vars) > 1) {
print_label("Sampling variables:")
print_items(x@vars, n = n)
}
newline()
print(x@control, n = n, level = level + 1)
invisible(x)
}
setShowDefault("Resample")
print.SelectedInput <- function(
x, n = MachineShop::settings("print_max"), id = FALSE, ...
) {
NextMethod()
level <- nesting_level(...)
nextlevel <- level + 1
if (level < 1) {
hline(level)
print_train_label("Selection set:")
newline()
print(x@candidates, n = n, level = nextlevel, id = id, data = FALSE)
hline(level)
print(x@params, n = n, level = nextlevel)
} else if (level == 1) {
newline()
print_train_label("Selection set:")
print(x@candidates, n = -n, level = nextlevel, id = id, data = FALSE)
}
invisible(x)
}
print.SequentialOptimization <- function(x, ...) {
NextMethod()
level <- nesting_level(...)
if (level < 1) {
print_fields(list("Fallback grid samples: " = if (x@random) x@random))
}
invisible(x)
}
format.SurvMatrix <- function(x, ...) {
format(as(x, "matrix"), ...)
}
#' @rdname print-methods
#'
print.SurvMatrix <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, pad = FALSE, ...)
print_items(as(x, "matrix"), n = n)
print_fields(list(
"Time{?s}: " = x@times,
"Distribution: " = x@distr
), n = n)
invisible(x)
}
setShowDefault("SurvMatrix")
#' @rdname print-methods
#'
print.SurvTimes <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, pad = FALSE, ...)
print_items(as(x, "numeric"), n = n)
print_fields(list("Distribution: " = x@distr))
invisible(x)
}
setShowDefault("SurvTimes")
print.TabularArray <- function(x, ...) {
print(as(x, "array"))
invisible(x)
}
setShowDefault("TabularArray")
print.TrainingParams <- function(
x, n = MachineShop::settings("print_max"), ...
) {
title(x, ...)
level <- nesting_level(...)
nextlevel <- level + 1
if (length(x@options)) {
print_str(x@options, label = "Option{?s}:", n = n)
newline()
}
if (is_optim_method(x)) {
print(x@optim, n = n, level = nextlevel)
newline()
print(x@control, n = n, level = nextlevel)
if (nextlevel < 0) {
newline()
print_label("Metrics:")
print(x@metrics)
newline()
print_fields(list("Cutoff: " = x@cutoff))
newline()
print_label("Stat:")
print(x@stat)
}
} else {
print(x@control, n = n, level = nextlevel)
}
invisible(x)
}
setShowDefault("TrainingParams")
#' @rdname print-methods
#'
print.TrainingStep <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, ...)
level <- nesting_level(...)
selected <- which(x@log$selected)
print_fields(list("Optimization method: " = x@method))
print_label(x@name, " log:")
print_items(x@log, n = n)
if (ndim(x@performance) > 2) {
newline()
print_fields(list(
"Selected row: " = selected,
"Metric: " = unlist(x@log$metrics[selected, 1])
), add_name = TRUE)
}
invisible(x)
}
setShowDefault("TrainingStep")
print.TunedInput <- function(x, n = MachineShop::settings("print_max"), ...) {
NextMethod()
level <- nesting_level(...)
nextlevel <- level + 1
if (level < 1) {
newline()
grid <- x@grid
if (isS4(grid)) {
print(grid, level = nextlevel)
} else {
heading("Grid", level = nextlevel)
print_items(grid, n = n)
}
newline()
print(x@params, n = n, level = nextlevel)
}
invisible(x)
}
print.TunedModel <- function(x, n = MachineShop::settings("print_max"), ...) {
title(x, ...)
level <- nesting_level(...)
nextlevel <- level + 1
trained <- is_trained(x)
print_modelinfo(x, trained = trained, ...)
if (level < 2) {
newline()
print(x@model, n = n, level = nextlevel)
if (level < 1) {
newline()
grid <- x@grid
if (isS4(grid)) {
print(grid, level = nextlevel)
} else {
heading("Grid", level = nextlevel)
print_items(grid, n = n)
}
newline()
print(x@params, n = n, level = nextlevel)
if (trained) {
newline()
print(x@steps, n = n, level = nextlevel)
}
}
}
invisible(x)
}
print.TuningGrid <- function(x, ...) {
title(x, ...)
print_fields(list("Grid size{?s}: " = x@size), add_names = TRUE)
print_fields(list("Random samples: " = x@random))
invisible(x)
}
setShowDefault("TuningGrid")
#' @rdname print-methods
#'
print.VariableImportance <- function(
x, n = MachineShop::settings("print_max"), ...
) {
x <- update(x)
title(x, pad = FALSE, ...)
print_fields(list(
"Method: " = x@method,
"Metric: " = x@metric,
"Scale: " = x@scale
))
print_label("Values:")
print_items(as(x, "data.frame"), n = n)
invisible(x)
}
setShowDefault("VariableImportance")
#################### Print Utility Functions ####################
format_len <- function(x) format(x, big.mark = ",")
heading <- function(x, level = 0, pad = TRUE, ...) {
style <- if (level < 0) {
make_ansi_style("magenta")
} else if (level == 0) {
make_ansi_style("green")
}
hline(level, label = style_bold(x), trim = level, style = style)
if (level < 2 && pad) newline()
}
hline <- function(symbol = 0, label = character(), trim = 0, style = NULL) {
if (is.numeric(symbol)) {
symbols <- c("-", "=", ".", "_", "~")
symbol <- symbols[symbol %% length(symbols) + 1]
}
freespace <- max(console_width(), 30)
if (length(label)) {
nsymbol <- 3
str <- strrep(symbol, nsymbol)
freespace <- freespace - nsymbol - 2
str[2] <- style_reset(ansi_strtrim(label, freespace - nsymbol))
if (trim < 1) {
freespace <- freespace - ansi_nchar(str[2])
str[3] <- strrep(symbol, freespace)
} else if (trim == 1) {
str[3] <- str[1]
}
str <- paste(str, collapse = " ")
} else {
str <- strrep(symbol, freespace)
}
if (!is.null(style)) str <- style(str)
cat(str, "\n", sep = "")
}
nesting_level <- function(level = 0, ...) {
level
}
new_print_progress <- function() {
res <- function(...) NULL
body(res) <- bquote(print_progress(..., start_time = .(Sys.time())))
res
}
newline <- function() {
cat("\n")
}
print_control <- function(x, fields = NULL, n = Inf, ...) {
level <- nesting_level(...)
title(x, ...)
print_fields(c(
list("Label: " = x@label),
fields
))
if (level < 1) {
print_fields(list("Case-weighted metrics: " = x@weights))
print_fields(x@predict, labels = c(
times = "Survival time{?s}: ",
distr = "Distribution: ",
method = "Method: "
), "Prediction parameters", n = n)
print_fields(x@strata, labels = c(
breaks = "Breaks: ",
nunique = "Unique numeric threshold: ",
prop = "Minimum proportion: ",
size = "Minimum size: "
), "Stratification parameters")
print_fields(list(
"Monitor: " = x@monitor,
"Seed: " = unname(x@seed)
), add_names = TRUE)
}
invisible(x)
}
print_data <- function(x, n = Inf, level = 0) {
if (level < 1) {
print_label("Data:")
x[["(names)"]] <- NULL
print_items(x, n = n)
} else if (level == 1) {
print_fields(list("Number of observations: " = nrow(x)))
}
}
print_default <- function(x, max = NULL, ...) {
if (identical(max, Inf)) max <- .Machine$integer.max
print(x, max = max, ...)
}
print_fields <- function(x, labels = character(), heading = character(), ...) {
if (is_empty(labels)) {
labels <- names(x)
names(labels) <- labels
}
label_names <- names(labels)
nzlengths <- lengths(x[label_names]) > 0
if (any(nzlengths)) {
indent <- 2 * (length(heading) > 0)
if (indent) print_label(heading)
for (name in label_names[nzlengths]) {
print_items(
as_string(x[[name]], sep = NULL), label = style_label(labels[name]),
indent = indent, exdent = indent + 2, ...
)
}
}
}
print_id <- function(x) {
print_fields(list("ID: " = x@id))
}
print_items <- function(x, ...) {
UseMethod("print_items")
}
print_items.default <- function(x, ...) {
print(x)
}
print_items.character <- function(
x, n = Inf, label = "", indent = 0, exdent = 0, add_names = FALSE,
add_size = FALSE, sep = ", ", style = NULL, ...
) {
lines <- ansi_strwrap(
note_items(label, x, add_names = add_names, add_size = add_size, sep = sep),
indent = indent, exdent = exdent
)
max_lines <- ceiling(log(n))
if (length(lines) > max_lines && length(x) > 1) {
nlines <- max(max_lines, 1)
lines <- head(lines, nlines)
key <- trimws(sep)
pattern <- paste0("[", key, "](?=([^`]*`[^`]*`)*[^`]*$)[^\\S]")
last_pattern <- paste0(pattern, "(?:.(?!", pattern, "))+$")
last_line <- gsub(last_pattern, key, lines[nlines], perl = TRUE)
last_line <- ansi_strtrim(last_line, console_width() - 4)
lines[nlines] <- paste0(last_line, style_extra(" ..."))
}
if (length(style)) lines <- style(lines)
writeLines(lines)
}
print_items.data.frame <- function(x, ...) {
print_items.matrix(format(x), ...)
}
print_items.formula <- function(x, exdent = 2, ...) {
x <- deparse1(x)
split <- regexpr("[+]", x)
if (split > 0) x <- c(substring(x, 1, split - 1), substring(x, split + 1))
print_items(x, exdent = exdent, sep = " + ", ...)
}
print_items.ListOf <- function(x, n = Inf, level = 0, ...) {
if (is_empty(x)) {
hline(level, label = "ListOf()")
} else {
labels <- map("char", function(name, i) {
if (nzchar(name)) {
prefix <- "$"
label <- deparse(as.name(name), backtick = TRUE)
} else {
prefix <- NULL
label <- paste0("[[", i, "]]")
}
if (i <= n) {
hline(level, label = paste0(prefix, label))
print(x[[i]], n = n, level = level, na.print = NULL, ...)
if (level < 2) newline()
}
label
}, make_names_along(x, "", unique = FALSE), seq_along(x))
n_more <- max(length(x) - n, 0)
if (n_more) {
extra <- tail(labels, n_more)
msg <- pluralize(
"... with ", format_len(n_more), " more element{?s}: ", "{qty(n_more)}"
)
print_items(extra, label = msg, n = n, style = style_extra)
if (level < 2) newline()
}
}
}
print_items.matrix <- function(x, n = Inf, ...) {
row_inds <- head(seq_len(nrow(x)), n)
col_inds <- head(seq_len(ncol(x)), n)
num_items <- length(row_inds) * length(col_inds)
if (num_items) {
print_default(x[row_inds, col_inds, drop = FALSE], max = num_items)
} else {
cat("<", format_len(nrow(x)), " x ", format_len(ncol(x)), " ", class1(x),
">\n", sep = "")
}
diff_rows <- nrow(x) - length(row_inds)
diff_cols <- ncol(x) - length(col_inds)
msg <- NULL
if (diff_rows) {
msg <- pluralize(format_len(diff_rows), " more row{?s}", "{qty(diff_rows)}")
}
if (diff_cols) {
msg <- c(
msg,
pluralize(format_len(diff_cols), " more column{?s}: ", "{qty(diff_cols)}")
)
print_extra <- function(msg) {
extra <- tail(colnames(x), diff_cols)
print_items(extra, label = msg, n = n, style = style_extra)
}
} else {
print_extra <- function(msg) cat(style_extra(msg), "\n", sep = "")
}
if (length(msg)) {
print_extra(paste("... with", as_string(msg, conj = "and")))
}
}
print_items.numeric <- function(x, n = Inf, ...) {
diff <- length(x) - n
if (diff > 0) {
print_default(head(x, n), max = n)
msg <- pluralize(
"... with ", format_len(diff), " more value{?s}", "{qty(diff)}"
)
cat(style_extra(msg), "\n", sep = "")
} else {
print_default(x, max = n)
}
}
print_items.tbl <- function(x, n = Inf, ...) {
print(x, n = n, max_footer_lines = ceiling(log(n)))
}
print_label <- function(...) {
cat(style_label(...), "\n", sep = "")
}
print_modelinfo <- function(x, trained = FALSE, level = 0, id = FALSE, ...) {
info_list <- modelinfo(x)
if (is_empty(info_list)) return(NULL)
info <- info_list[[1]]
print_fields(list(
"Model name: " = names(info_list),
"Label: " = paste0(if (trained) "Trained ", info$label)
))
if (id) print_id(x)
if (level < 1) {
print_fields(info, labels = c(
packages = "Package{?s}: ",
response_types = "Response type{?s}: ",
weights = "Case weights support: ",
na.rm = "Missing case removal: ",
grid = "Tuning grid: ",
varimp = "Variable importance: "
))
}
}
print_progress <- function(
scores, max_iter = Inf, method = character(), items = list(),
n = MachineShop::settings("print_max"), metric = numeric(),
start_time = Sys.time(), pad = TRUE
) {
iter <- length(scores)
hline(label = paste0(
"Iteration ", iter, if (is.finite(max_iter)) paste0(" of ", max_iter)
))
newline()
selected <- which.max(scores)
if (selected == iter) selected <- paste0(">", selected, "<")
print_fields(list("Optimization method: " = method))
print_fields(items, add_size = TRUE, add_names = TRUE, n = n)
print_fields(list(
"Metric: " = metric,
"Current maximum score (iteration): " = as_string(list(
max(scores), paste0("(", selected, ")")
), sep = " "),
"Elapsed time: " = round(difftime(Sys.time(), start_time), 1)
), add_names = TRUE)
if (pad && iter < max_iter) newline()
}
print_str <- function(x, label, n = Inf) {
print_label(pluralize(label, "{qty(length(x))}"))
cat(str(x, give.attr = FALSE, list.len = n))
}
print_train_label <- function(...) {
print_label(style_bold(...))
}
style_extra <- make_ansi_style("grey")
style_label <- make_ansi_style("blue")
title <- function(x, ...) {
heading(paste(class1(x), "object"), ...)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.