Nothing
#' Format a data frame for printing
#' @description An internal helper function that rounds the numeric columns of a
#' data frame based on a named list of digits.
#' @param x A data frame or a list that can be coerced into a data frame.
#' @param digits A named numeric vector where names correspond to column names
#' in `x` and values specify the number of decimal places. A special name
#' `"default__"` can set a default rounding for all other numeric columns.
#' @return A formatted data frame with numeric columns rounded.
#' @noRd
format_show <- function(x, digits) {
r <- as.data.frame(lapply(1:length(x), function(i) {
if (!is.character(x[[i]])) {
if (names(x)[i] %in% names(digits)) {
round(x[[i]], digits[names(x)[i]])
} else {
round(x[[i]], digits["default__"])
}
} else {
return(x[[i]])
}
}))
names(r) <- names(x)
rownames(r) <- rownames(x)
return(r)
}
#' Concatenate strings
#' @description A lightweight wrapper for `paste(..., collapse = "", sep = "")`.
#' @param ... Objects to be converted to character vectors and concatenated.
#' @return A single character string.
#' @noRd
concat <- function(...) {
paste(..., collapse = "", sep = "")
}
#' Compute standard errors from a model object
#' @description Extracts the standard errors by taking the square root of the
#' diagonal elements of a model's variance-covariance matrix.
#' @param model A fitted model object that has a `vcov` method.
#' @return A numeric vector of standard errors.
#' @noRd
se <- function(model) {
sqrt(diag(vcov(model)))
}
#' Wickham's Histospark
#' @details
#' <https://github.com/hadley/precis/blob/master/R/histospark.R>
#' Copyright Hadley Wickham 2016
#' Released under GPL-3
#' @param x A numeric vector.
#' @param width The width of the sparkline in characters.
#' @return A character string representing the histogram.
#' @noRd
sparks <- c("\u2581", "\u2582", "\u2583", "\u2585", "\u2587")
histospark <- function(x, width = 10) {
if (all(is.na(x))) {
return(paste0(rep(" ", width), collapse = ""))
}
bins <- graphics::hist(x, breaks = width, plot = FALSE)
factor <- cut(
bins$counts / max(bins$counts),
breaks = seq(0, 1, length = length(sparks) + 1),
labels = sparks,
include.lowest = TRUE
)
paste0(factor, collapse = "")
}
#' The 'describe' class for object summaries
#'
#' @description An S4 class that holds a summary data frame and formatting
#' information. It extends the `data.frame` class and is the return type for
#' the [describe()] function.
#'
#' @slot digits A numeric value indicating the number of digits to display.
#' @name describe-class
#' @rdname describe-class
#' @export
setClass("describe", slots = c(digits = "numeric"), contains = "data.frame")
#' Show method for 'describe' objects
#' @description Internal implementation for the `show` method.
#' @param object A `describe` class object.
#' @noRd
describe_show <- function(object) {
# print( round( object@output , object@digits ) )
r <- format_show(object, digits = c("default__" = object@digits, "n_eff" = 0))
has_header <- !is.null(attr(object, "header"))
if (has_header) {
# show header
cat(attr(object, "header"))
cat("\n")
}
print(r)
}
#' @rdname describe-class
#' @param object An object of class `describe`.
#' @export
setMethod("show", "describe", function(object) describe_show(object))
#' Describe an object
#'
#' @description `describe` provides a flexible summary of various R objects,
#' such as data frames or Blimp model objects. It is an
#' alternative to `summary` and is inspired by `precis` from the `rethinking` package.
#'
#' @author The `data.frame` method is adapted from Richard McElreath's `precis`
#' function in the `rethinking` package (\url{https://github.com/rmcelreath/rethinking}).
#' The `histospark` function is by Hadley Wickham (GPL-3).
#' The `blimp_obj` method was written for this package.
#'
#' @param object The object to describe.
#' @param depth An integer (`1`, `2`, or `3`) that controls the display of vector
#' and matrix parameters. `depth=1` (default) shows only scalar parameters.
#' `depth=2` shows scalars and vectors. `depth=3` shows all parameters.
#' @param pars An optional character vector of parameter names to include in the summary.
#' @param prob The probability mass for the credible interval (e.g., quantile interval).
#' @param digits The number of decimal places to display in the output.
#' @param sort An optional character string specifying a column name to sort the results by.
#' @param decreasing Logical. If `TRUE`, sorting is in decreasing order.
#' @param ... Additional arguments passed to specific methods.
#'
#' @return An object of class [describe-class], which is a data frame containing
#' summary statistics and attributes for printing.
#' @name describe
#' @aliases describe-methods
#' @export
setGeneric(
"describe",
function(object, depth = 1, pars, prob = 0.95, digits = 2, sort = NULL, decreasing = FALSE, ...) {
new("describe", as.data.frame(object), digits = digits)
}
)
#' Format describe output
#' @description An internal helper function to handle depth filtering and
#' sorting of the summary data frame produced by `describe` methods.
#' @param result The data frame of summary statistics.
#' @param depth Integer (`1`, `2`, or `3`) to control parameter display depth.
#' @param sort Column name to sort by, or `NULL`.
#' @param decreasing Logical sort order.
#' @return A formatted data frame.
#' @noRd
describe_format <- function(result, depth, sort, decreasing) {
# deal with depth
if (depth == 1) {
hits <- regexpr("]", rownames(result), fixed = TRUE)
hits_idx <- which(hits > -1)
if (length(hits_idx) > 0) {
result <- result[-hits_idx, ]
message(paste(length(hits_idx), "vector or matrix parameters hidden. Use depth=2 to show them."))
}
}
if (depth == 2) {
hits <- regexpr(",", rownames(result), fixed = TRUE)
hits_idx <- which(hits > -1)
if (length(hits_idx) > 0) {
result <- result[-hits_idx, ]
message(paste(length(hits_idx), "matrix parameters hidden. Use depth=3 to show them."))
}
}
# sort
if (!is.null(sort)) {
o <- order(result[, sort], decreasing = decreasing)
result <- result[o, ]
}
# label Rhat with version
rhat_col <- which(colnames(result) == "Rhat")
if (!is.null(rhat_col)) {
colnames(result)[rhat_col] <- "Rhat4"
}
return(result)
}
#' @rdname describe
#' @param hist Logical. If `TRUE` (and on a Unix-like OS), a unicode histogram
#' (`histospark`) is included in the output. Defaults to `TRUE`.
#' @export
setMethod(
"describe", "data.frame",
function(object, depth = 1, pars, prob = 0.50, digits = 2, sort = NULL, decreasing = FALSE, hist = TRUE, ...) {
plo <- (1 - prob) / 2
phi <- 1 - plo
# replace any character or factor columns with NA numeric columns
# histospark will detect all NA and return blank line
for (i in 1:ncol(object)) {
if (class(object[[i]]) %in% c("factor", "character")) {
object[[i]] <- as.numeric(rep(NA, nrow(object)))
}
}
if (hist == TRUE && (.Platform$OS.type == "unix")) {
result <- data.frame(
mean = apply(object, 2, mean, na.rm = TRUE),
median = apply(object, 2, median, na.rm = TRUE),
sd = apply(object, 2, sd, na.rm = TRUE),
lo = apply(object, 2, quantile, na.rm = TRUE, probs = plo),
hi = apply(object, 2, quantile, na.rm = TRUE, probs = phi),
histogram = apply(object, 2, histospark),
stringsAsFactors = FALSE
)
} else {
# no unicode histogram
result <- data.frame(
mean = apply(object, 2, mean, na.rm = TRUE),
median = apply(object, 2, median, na.rm = TRUE),
sd = apply(object, 2, sd, na.rm = TRUE),
lo = apply(object, 2, quantile, na.rm = TRUE, probs = plo),
hi = apply(object, 2, quantile, na.rm = TRUE, probs = phi),
stringsAsFactors = FALSE
)
}
colnames(result)[4:5] <- paste(c(plo, phi) * 100, "%", sep = "")
result <- describe_format(result, depth, sort, decreasing)
has_source <- !is.null(attr(object, "source"))
header_string <- concat("'data.frame': ", nrow(object), " obs. of ", ncol(object), " variables:")
if (has_source) {
header_string <- attr(object, "source")
}
attr(result, "header") <- header_string
return(new("describe", result, digits = digits))
}
)
#' @rdname describe
#' @export
setMethod(
"describe", "blimp_obj",
function(object, depth = 1, pars, prob = 0.95, digits = 2, sort = NULL, decreasing = FALSE, hist = TRUE, ...) {
tmp <- object@iterations
names(tmp) <- rownames(object@estimates)
plo <- (1 - prob) / 2
phi <- 1 - plo
# replace any character or factor columns with NA numeric columns
# histospark will detect all NA and return blank line
for (i in 1:ncol(tmp)) {
if (class(tmp[[i]]) %in% c("factor", "character")) {
tmp[[i]] <- as.numeric(rep(NA, nrow(tmp)))
}
}
if (hist == TRUE) {
result <- data.frame(
mean = apply(tmp, 2, mean, na.rm = TRUE),
median = apply(tmp, 2, median, na.rm = TRUE),
sd = apply(tmp, 2, sd, na.rm = TRUE),
lo = apply(tmp, 2, quantile, na.rm = TRUE, probs = plo),
hi = apply(tmp, 2, quantile, na.rm = TRUE, probs = phi),
histogram = apply(tmp, 2, histospark),
stringsAsFactors = FALSE
)
} else {
# no unicode histogram
result <- data.frame(
mean = apply(tmp, 2, mean, na.rm = TRUE),
median = apply(tmp, 2, median, na.rm = TRUE),
sd = apply(tmp, 2, sd, na.rm = TRUE),
lo = apply(tmp, 2, quantile, na.rm = TRUE, probs = plo),
hi = apply(tmp, 2, quantile, na.rm = TRUE, probs = phi),
stringsAsFactors = FALSE
)
}
colnames(result)[4:5] <- paste(c(plo, phi) * 100, "%", sep = "")
result <- describe_format(result, depth, sort, decreasing)
has_source <- !is.null(attr(tmp, "source"))
header_string <- concat("'blimp_obj': ", ncol(tmp), " parameters summarized over ", nrow(tmp), " iterations:")
if (has_source) {
header_string <- attr(tmp, "source")
}
attr(result, "header") <- header_string
return(new("describe", result, digits = digits))
}
)
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.