diff --git a/.Rbuildignore b/.Rbuildignore index e81d5d72e..de933741f 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -37,4 +37,5 @@ trash.* ^altdoc$ ^_quarto$ ^_quarto/ -inst/tinytest/tinytable_assets/ \ No newline at end of file +inst/tinytest/tinytable_assets/ + diff --git a/DESCRIPTION b/DESCRIPTION index dec443c8c..0f72360e4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -9,7 +9,7 @@ Description: Create beautiful and customizable tables to summarize several RTF, JPG, or PNG. Tables can easily be embedded in 'Rmarkdown' or 'knitr' dynamic documents. Details can be found in Arel-Bundock (2022) . -Version: 1.9.9.9999 +Version: 2.0.0.12 Authors@R: c(person("Vincent", "Arel-Bundock", email = "vincent.arel-bundock@umontreal.ca", role = c("aut", "cre"), @@ -58,7 +58,7 @@ Imports: parameters (>= 0.21.6), performance (>= 0.10.9), tables (>= 0.9.17), - tinytable (> 0.2.0) + tinytable (>= 0.3.0) Suggests: AER, altdoc, @@ -88,6 +88,7 @@ Suggests: gtExtras, haven, huxtable, + labelled, IRdisplay, ivreg, kableExtra, diff --git a/Makefile b/Makefile index 68198f62e..0c4bb7cfe 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ check: document ## devtools::check() install: document ## devtools::install() # R CMD INSTALL . - Rscript -e "devtools::install(dependencies = TRUE)" + Rscript -e "devtools::install(dependencies = FALSE)" deps: ## install dependencies Rscript -e "devtools::install(dependencies = TRUE)" diff --git a/NEWS.md b/NEWS.md index 8bea0242f..bf69cb82f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,32 @@ # News +## Development + +New features: + +* `modelsummary()` gets a `gof_function` argument which accepts functions to extract custom information from models. +* `flextable`: Support spanning column headers + +`datasummary_balance()`: + +* `formula` can now include variables on the left-hand side to indicate the subset of columns to summarize: `datasummary_balance(mpg + hp ~ am, data = mtcars)` Thanks to @etiennebacher for feature request #751. + +Minor: + +* Unnecessary text printed to screen on some F stat computations is now suppressed. +* Update to `tinytable` 0.3.0 + +Bugs: + +* `escape` argument not respected in `datasummary_df()`. Thanks to @adamaltmejd for report #740 +* `datasummary_correlation()` supports `data.table`. Thanks to volatilehead on Twitter for report #737. +* Accepts named `estimate` argument when using shape and statistics are horizontal. Thanks to @iago-pssjd for report #745. +* Labelled values but no label for variable broke `datasummary()`. Thanks to @marklhc for report #752. +* `coef_map` does not work when there is a `group`. Thanks to @mccarthy-m-g for report #757. +* `kableExtra`: fix spanning column headers when using the `shape` argument. +* Multiple footnotes and line breaks in footnotes are now allowed in `tinytable` output. Thanks to + + ## 2.0.0 MAJOR BREAKING CHANGE: The default output format is now `tinytable` instead of `kableExtra`. Learn more about `tinytable` here: @@ -24,16 +51,20 @@ New features: * `datasummary_skim()`: - New `type="all"` by default to display both numeric and categorical variables in a single table with distinct panels. This feature is only available with the `tinytable` backend (default). + - `by` argument allows summarizing numeric variables by group. - `fun_numeric` argument accepts a list of functions to control the summary columns. * `modelsummary()`: - `statistic` and `estimate` can be specified as named vectors to control the names of statistics when displayed in different columns using the `shape` argument. (Thanks to @mps9506 for bug report #722) - `modelsummary(panels, shape = "cbind")` automatically adds column-spanning labels when `panels` is a named nested list of models. * `config_modelsummary()` gets a `startup_message` argument to silence the startup message persistently. +* Improved documentation and vignettes, providing clearer instructions and examples. +* Updated tests and snapshots to ensure reliability and consistency across changes. Bug fixes: * Fixed Issue #399: datasummary_balance() siunitx formatting. * Fixed Issue #782: Useless warning in some `modelplot()` calls. Thanks to @iago-pssjd for the report and @florence-laflamme for the fix. +* Addressed various bugs and made optimizations for better performance and user experience. ## 1.4.5 diff --git a/R/datasummary_balance.R b/R/datasummary_balance.R index 3d06f1707..f1f39d404 100644 --- a/R/datasummary_balance.R +++ b/R/datasummary_balance.R @@ -8,9 +8,10 @@ #' * https://modelsummary.com/ #' * https://modelsummary.com/articles/datasummary.html #' -#' @param formula a one-sided formula with the "condition" or "column" variable -#' on the right-hand side. ~1 can be used to show summary statistics for the -#' full data set +#' @param formula +#' + `~1`: show summary statistics for the full dataset +#' + one-sided formula: with the "condition" or "column" variable on the right-hand side. +#' + two-side formula: with the subset of variables to summarize on the left-hand side and the condition variable on the right-hand side. #' @param data A data.frame (or tibble). If this data includes columns called #' "blocks", "clusters", and/or "weights", the "estimatr" package will consider #' them when calculating the difference in means. If there is a `weights` @@ -376,10 +377,22 @@ sanitize_datasummary_balance_data <- function(formula, data) { # includes All()) sanity_ds_data(All(data) ~ x + y, data) + # rhs condition variable + rhs <- labels(stats::terms(formula)) + + # LHS selects columns + lhs <- stats::update(formula, ".~1") + lhs <- all.vars(lhs) + lhs <- setdiff(lhs, ".") + if (length(lhs) > 0) { + cols <- intersect(c(lhs, rhs), colnames(data)) + if (length(cols) > 1) { + data <- data[, cols, drop = FALSE] + } + } + if (formula != ~1) { - # rhs condition variable - rhs <- labels(stats::terms(formula)) if (!rhs %in% colnames(data)) { stop("Variable ", rhs, " must be in data.") diff --git a/R/datasummary_correlation.R b/R/datasummary_correlation.R index a7dddb4cd..18086a9bf 100644 --- a/R/datasummary_correlation.R +++ b/R/datasummary_correlation.R @@ -171,6 +171,7 @@ datasummary_correlation <- function(data, # subset numeric and compute correlation if (easycorrelation == FALSE) { + out <- data.frame(data, check.names = FALSE) # data.table & tibble out <- data[, sapply(data, is.numeric), drop = FALSE] out <- fn(out) } else { diff --git a/R/datasummary_df.R b/R/datasummary_df.R index 6d7c15dd9..9b559dce5 100644 --- a/R/datasummary_df.R +++ b/R/datasummary_df.R @@ -36,6 +36,7 @@ datasummary_df <- function(data, notes = notes, output = output, title = title, + escape = escape, add_rows = add_rows, add_columns = add_columns, ...) diff --git a/R/datasummary_skim.R b/R/datasummary_skim.R index e51f1ca62..e5df5cd4a 100644 --- a/R/datasummary_skim.R +++ b/R/datasummary_skim.R @@ -97,7 +97,7 @@ datasummary_skim <- function(data, if (inherits(a, "tinytable") && inherits(b, "tinytable")) { out <- tinytable::rbind2(a, b, use_names = FALSE) - out <- tinytable::format_tt(out, replace_na = "") + out <- tinytable::format_tt(out, replace = "") out <- tinytable::style_tt(out, i = nrow(a) + 1, line = "t", line_size = .3) if (settings_equal("output_format", "html")) { out <- tinytable::style_tt(out, i = nrow(a) + 1, bold = TRUE, line = "bt", line_color = "#d3d8dc") diff --git a/R/factory.R b/R/factory.R index 0545fe73e..b118fdd82 100644 --- a/R/factory.R +++ b/R/factory.R @@ -50,7 +50,7 @@ factory <- function(tab, # flat header if necessary flat_header <- attr(tab, 'header_sparse_flat') if (!is.null(flat_header)) { - flat_factories <- c('flextable', 'huxtable', 'dataframe', 'typst') + flat_factories <- c('huxtable', 'dataframe', 'typst') flat_formats <- c('markdown', 'word', 'powerpoint', 'typst') if (settings_get("output_factory") %in% flat_factories || settings_get("output_format") %in% flat_formats) { diff --git a/R/factory_flextable.R b/R/factory_flextable.R index f64264f14..f04460508 100644 --- a/R/factory_flextable.R +++ b/R/factory_flextable.R @@ -12,7 +12,9 @@ factory_flextable <- function(tab, insight::check_if_installed("flextable") - colnames(tab) <- gsub("\\|\\|\\|\\|", " / ", colnames(tab)) + span <- get_span_kableExtra(tab) + colnames(tab) <- gsub(".*\\|\\|\\|\\|", "", colnames(tab)) + colnames(tab) <- pad(colnames(tab)) # measurements table_width <- ncol(tab) @@ -39,6 +41,15 @@ factory_flextable <- function(tab, default = theme_ms_flextable) out <- theme_ms(out, hrule = hrule) + # spanning headers + for (i in seq_along(span)) { + out <- flextable::add_header_row(out, + colwidths = span[[i]], + values = names(span[[i]]) + ) + } + + # output if (is.null(settings_get("output_file"))) { return(out) diff --git a/R/factory_kableExtra.R b/R/factory_kableExtra.R index 5e825b85b..38533f3b4 100644 --- a/R/factory_kableExtra.R +++ b/R/factory_kableExtra.R @@ -118,6 +118,9 @@ factory_kableExtra <- function(tab, colnames(tab)[idx] <- paste0(" ", colnames(tab)[idx]) } + # issue #761: only matters for shape + colnames(tab) <- gsub(".*\\|\\|\\|\\|", "", colnames(tab)) + # create tables with combined arguments arguments <- arguments[base::intersect(names(arguments), valid)] arguments <- c(list(tab), arguments) diff --git a/R/format_estimates.R b/R/format_estimates.R index 066d5ba38..cba9ee8ce 100644 --- a/R/format_estimates.R +++ b/R/format_estimates.R @@ -6,6 +6,7 @@ format_estimates <- function( est, estimate, + estimate_label, statistic, vcov, conf_level, @@ -17,6 +18,9 @@ format_estimates <- function( ...) { + # when length(estimate) > 1, we want different stat and we want to allow labels + if (is.null(estimate_label)) estimate_label <- "estimate" + # conf.int to glue estimate_glue <- ifelse( estimate == "conf.int", @@ -125,7 +129,6 @@ format_estimates <- function( } } - ## round all ## ensures that the reshape doesn't produce incompatible types ## exclude factors and characters, otherwise `rounding` will escape them @@ -155,7 +158,6 @@ format_estimates <- function( } } - # extract estimates (there can be several) for (i in seq_along(estimate_glue)) { s <- estimate_glue[i] @@ -222,12 +224,13 @@ format_estimates <- function( est[[col]] <- as.character(est[[col]]) } + # statistics need informative names idx <- as.numeric(factor(est$statistic)) # estimates are one per model, but all displayed on the same row, so we give # the same identifier. statistics have different names because they need to # be merged. - est$statistic <- c("estimate", statistic)[idx] + est$statistic <- c(estimate_label, statistic)[idx] # drop empty rows (important for broom.mixed which produces group # estimates without standard errors) diff --git a/R/get_gof.R b/R/get_gof.R index 5e2a8a5e2..5db7b1730 100644 --- a/R/get_gof.R +++ b/R/get_gof.R @@ -5,10 +5,11 @@ #' can access this information by calling the `attributes` function: #' `attributes(get_estimates(model))` #' -#' @inheritParams get_estimates #' @param vcov_type string vcov type to add at the bottom of the table +#' @inheritParams get_estimates +#' @inheritParams modelsummary #' @export -get_gof <- function(model, vcov_type = NULL, ...) { +get_gof <- function(model, gof_function = NULL, vcov_type = NULL, ...) { # secret argument passed internally # gof_map = NULL: no value supplied by the user @@ -16,6 +17,8 @@ get_gof <- function(model, vcov_type = NULL, ...) { dots <- list(...) if (isTRUE(is.na(dots$gof_map))) return(NULL) + checkmate::assert_function(gof_function, null.ok = TRUE) + # priority get_priority <- getOption("modelsummary_get", default = "easystats") checkmate::assert_choice( @@ -61,27 +64,44 @@ get_gof <- function(model, vcov_type = NULL, ...) { } # internal customization by modelsummary - gof_custom <- glance_custom_internal(model, vcov_type = vcov_type, gof = gof) - if (!is.null(gof_custom) && is.data.frame(gof)) { - for (n in colnames(gof_custom)) { + gof_custom_df <- glance_custom_internal(model, vcov_type = vcov_type, gof = gof, gof_function = gof_function) + if (!is.null(gof_custom_df) && is.data.frame(gof)) { + for (n in colnames(gof_custom_df)) { # modelsummary's vcov argument has precedence # mainly useful to avoid collision with `fixest::glance_custom` overwriteable <- c("IID", "Default", "") if (is.null(vcov_type) || n != "vcov.type" || gof[["vcov.type"]] %in% overwriteable) { - gof[[n]] <- gof_custom[[n]] + gof[[n]] <- gof_custom_df[[n]] } } } # glance_custom (vcov_type arg is needed for glance_custom.fixest) - gof_custom <- glance_custom(model) - if (!is.null(gof_custom) && is.data.frame(gof)) { - for (n in colnames(gof_custom)) { + gof_custom_df <- glance_custom(model) + if (!is.null(gof_custom_df) && is.data.frame(gof)) { + for (n in colnames(gof_custom_df)) { # modelsummary's vcov argument has precedence # mainly useful to avoid collision with `fixest::glance_custom` if (is.null(vcov_type) || n != "vcov.type") { - gof[[n]] <- gof_custom[[n]] + gof[[n]] <- gof_custom_df[[n]] + } + } + } + + # gof_function function supplied directly by the user + if (is.function(gof_function)) { + if (!"model" %in% names(formals(gof_function))) { + msg <- "`gof_function` must accept an argument named 'model'." + insight::format_error(msg) + } + tmp <- try(gof_function(model = model)) + if (!isTRUE(checkmate::check_data_frame(tmp, nrows = 1, col.names = "unique"))) { + msg <- "`gof_function` must be a function which accepts a model and returns a 1-row data frame with unique column names." + insight::format_error(msg) + } else { + for (n in names(tmp)) { + gof[[n]] <- tmp[[n]] } } } diff --git a/R/get_vcov.R b/R/get_vcov.R index 51b7ab1ca..d4c8fffa9 100644 --- a/R/get_vcov.R +++ b/R/get_vcov.R @@ -27,6 +27,7 @@ get_vcov.default <- function(model, vcov = NULL, ...) { return(out) } else if (isTRUE(checkmate::check_character(vcov, len = 1))) { + if (isTRUE(vcov == "bootstrap")) vcov <- "vcovBS" out <- insight::get_varcov(model, vcov = vcov, vcov_args = dots, component = "all") } else if (isTRUE(checkmate::check_formula(vcov))) { diff --git a/R/map_estimates.R b/R/map_estimates.R index 4516aacb7..d49b4c792 100644 --- a/R/map_estimates.R +++ b/R/map_estimates.R @@ -80,13 +80,15 @@ modelsummary(mod, coef_omit = "^(?!.*ei|.*pt)") } idx <- estimates$term %in% names(coef_map) if (!any(idx)) { - stop("At least one of the term names in each model must appear in `coef_map`.") + stop("At least one of the term names in each model must appear in `coef_map`.", call. = FALSE) } estimates <- estimates[idx, , drop = FALSE] + args <- list(match(estimates$term, names(coef_map)), seq_len(nrow(estimates))) estimates$term <- replace_dict( estimates$term, coef_map, interaction = !isTRUE(is.function(coef_rename))) + estimates <- estimates[do.call(order, args),] } # group_map @@ -108,4 +110,4 @@ modelsummary(mod, coef_omit = "^(?!.*ei|.*pt)") } return(estimates) -} \ No newline at end of file +} diff --git a/R/methods_stats.R b/R/methods_stats.R index 40a68b8cf..ff0d5725a 100644 --- a/R/methods_stats.R +++ b/R/methods_stats.R @@ -20,7 +20,9 @@ glance_custom_internal.lm <- function(x, vcov_type = NULL, gof = NULL, ...) { if (inherits(gof, "data.frame") && "statistic" %in% colnames(gof)) { out[["F"]] <- gof$statistic } else { - fstat <- try(lmtest::waldtest(x, vcov = stats::vcov)$F[2], silent = TRUE) + if (isTRUE(check_dependency("lmtest"))) { + void <- utils::capture.output(fstat <- try(lmtest::waldtest(x, vcov = stats::vcov)$F[2], silent = TRUE)) + } if (inherits(fstat, "numeric")) { out[["F"]] <- fstat } diff --git a/R/modelsummary.R b/R/modelsummary.R index 59c677f6f..1c7b1df6f 100644 --- a/R/modelsummary.R +++ b/R/modelsummary.R @@ -65,23 +65,24 @@ globalVariables(c('.', 'term', 'part', 'estimate', 'conf.high', 'conf.low', #' * TRUE: +=.1, *=.05, **=.01, ***=0.001 #' * Named numeric vector for custom stars such as `c('*' = .1, '+' = .05)` #' * Note: a legend will not be inserted at the bottom of the table when the `estimate` or `statistic` arguments use "glue strings" with `{stars}`. -#' @param statistic vector of strings or `glue` strings which select uncertainty -#' statistics to report vertically below the estimate. NULL omits all -#' uncertainty statistics. -#' * "conf.int", "std.error", "statistic", "p.value", "conf.low", "conf.high", . -#' or any column name produced by `get_estimates(model)` +#' @param statistic vector of strings or `glue` strings which select uncertainty statistics to report vertically below the estimate. NULL omits all uncertainty statistics. +#' * "conf.int", "std.error", "statistic", "p.value", "conf.low", "conf.high", or any column name produced by `get_estimates(model)` #' * `glue` package strings with braces, with or without R functions, such as: #' - `"{p.value} [{conf.low}, {conf.high}]"` #' - `"Std.Error: {std.error}"` #' - `"{exp(estimate) * std.error}"` -#' * Numbers are automatically rounded and converted to strings. To apply functions to their numeric values, as in the last `glue` example, users must set `fmt=NULL`. -#' * Parentheses are added automatically unless the string includes `glue` curly braces `{}`. -#' * Some statistics are not supported for all models. See column names in `get_estimates(model)`, and visit the website to learn how to add custom statistics. +#' - Numbers are automatically rounded and converted to strings. To apply functions to their numeric values, as in the last `glue` example, users must set `fmt=NULL`. +#' - Parentheses are added automatically unless the string includes `glue` curly braces `{}`. +#' * Notes: +#' - The names of the `statistic` are used a column names when using the `shape` argument to display statistics as columns: +#' - `statistic=c("p"="p.value", "["="conf.low", "]"="conf.high")` +#' - Some statistics are not supported for all models. See column names in `get_estimates(model)`, and visit the website to learn how to add custom statistics. #' @param vcov robust standard errors and other manual statistics. The `vcov` #' argument accepts six types of input (see the 'Details' and 'Examples' #' sections below): #' * NULL returns the default uncertainty estimates of the model object -#' * string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for `NULL`, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the `sandwich` package, or equivalent method. The behavior of those functions can (and sometimes *must*) be altered by passing arguments to `sandwich` directly from `modelsummary` through the ellipsis (`...`), but it is safer to define your own custom functions as described in the next bullet. +#' * string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for `NULL`, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the `sandwich` package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the `sandwich::vcovBS()`. The behavior of those functions can (and sometimes *must*) be altered by passing arguments to `sandwich` directly from `modelsummary` through the ellipsis (`...`), but it is safer to define your own custom functions as described in the next bullet. +#' #' * function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., `stats::vcov`, `sandwich::vcovHC`, `function(x) vcovPC(x, cluster="country")`). #' * formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid). #' * named list of `length(models)` variance-covariance matrices with row and column names equal to the names of your coefficient estimates. @@ -127,6 +128,7 @@ globalVariables(c('.', 'term', 'part', 'estimate', 'conf.high', 'conf.low', #' * `"IC"`: omit statistics matching the "IC" substring. #' * `"BIC|AIC"`: omit statistics matching the "AIC" or "BIC" substrings. #' * `"^(?!.*IC)"`: keep statistics matching the "IC" substring. +#' @param gof_function function which accepts a model object in the `model` argument and returns a 1-row `data.frame` with one custom goodness-of-fit statistic per column. #' @param group_map named or unnamed character vector. Subset, rename, and #' reorder coefficient groups specified a grouping variable specified in the #' `shape` argument formula. This argument behaves like `coef_map`. @@ -370,6 +372,7 @@ modelsummary <- function( coef_rename = FALSE, gof_map = NULL, gof_omit = NULL, + gof_function = NULL, group_map = NULL, add_columns = NULL, add_rows = NULL, @@ -400,6 +403,7 @@ modelsummary <- function( coef_rename = coef_rename, gof_map = gof_map, gof_omit = gof_omit, + gof_function = gof_function, add_columns = add_columns, add_rows = add_rows, align = align, @@ -453,6 +457,8 @@ modelsummary <- function( sanity_coef(coef_map, coef_rename, coef_omit) sanity_stars(stars) sanity_align(align, estimate = estimate, statistic = statistic, stars = stars) + checkmate::assert_function(gof_function, null.ok = TRUE) + # confidence intervals are expensive if (!any(grepl("conf", c(estimate, statistic)))) { @@ -501,6 +507,7 @@ modelsummary <- function( conf_level = conf_level, vcov = vcov, gof_map = gof_map, # check if we can skip all gof computation + gof_function = gof_function, shape = shape, coef_rename = coef_rename, ...) @@ -525,6 +532,8 @@ modelsummary <- function( est = msl[[i]]$tidy, fmt = fmt, estimate = estimate[[i]], + # enforce single name when multiple estimates in different colums + estimate_label = names(estimate)[1], statistic = statistic, vcov = vcov[[i]], conf_level = conf_level, @@ -836,7 +845,7 @@ modelsummary <- function( } -get_list_of_modelsummary_lists <- function(models, conf_level, vcov, gof_map, shape, coef_rename, ...) { +get_list_of_modelsummary_lists <- function(models, conf_level, vcov, gof_map, gof_function, shape, coef_rename, ...) { number_of_models <- max(length(models), length(vcov)) @@ -852,7 +861,7 @@ get_list_of_modelsummary_lists <- function(models, conf_level, vcov, gof_map, sh } # don't waste time if we are going to exclude all gof anyway - gla <- get_gof(models[[j]], vcov_type = names(vcov)[i], gof_map = gof_map, ...) + gla <- get_gof(models[[j]], vcov_type = names(vcov)[i], gof_map = gof_map, gof_function = gof_function, ...) tid <- get_estimates( models[[j]], diff --git a/R/modelsummary_rbind.R b/R/modelsummary_rbind.R index f22d2cf53..53d68dade 100644 --- a/R/modelsummary_rbind.R +++ b/R/modelsummary_rbind.R @@ -34,6 +34,7 @@ modelsummary_rbind <- function( coef_rename = FALSE, gof_map = NULL, gof_omit = NULL, + gof_custom = NULL, add_columns = NULL, add_rows = NULL, align = NULL, @@ -124,6 +125,7 @@ modelsummary_rbind <- function( group_map = NULL, gof_map = gof_map, gof_omit = gof_omit, + gof_custom = gof_custom, escape = escape ), keep.null = TRUE) tab <- do.call("modelsummary", args) diff --git a/R/rename_statistics.R b/R/rename_statistics.R index 6de191fe2..e2f280ebe 100644 --- a/R/rename_statistics.R +++ b/R/rename_statistics.R @@ -10,13 +10,20 @@ rename_statistics <- function(x, conf_level = 0.95, statistic = NULL, estimate = "estimate" = "Est.", "std.error" = "S.E.", "p.value" = "p", - "statistic" = "t") + "statistic" = "t", + "{estimate}" = "Est.", + "{std.error}" = "S.E.", + "{p.value}" = "p", + "{statistic}" = "t", + "{stars}" = "" + ) if (!is.null(names(estimate))) { for (i in seq_along(estimate)) { dict[[estimate[[i]]]] <- names(estimate)[i] } } + if (!is.null(names(statistic))) { # Otherwise model indentifiers get flatted in things like # `statistic = c("Confidence interval" = "conf.int")` @@ -27,11 +34,5 @@ rename_statistics <- function(x, conf_level = 0.95, statistic = NULL, estimate = } out <- replace_dict(x, dict) - # glue string - out <- gsub("\\{estimate\\}", "Est. ", out) - out <- gsub("\\{std.error\\}", "S.E. ", out) - out <- gsub("\\{p.value\\}", "p ", out) - out <- gsub("\\{statistic\\}", "t", out) - out <- gsub("\\{stars\\}", "", out) return(out) } diff --git a/R/sanitize_vcov.R b/R/sanitize_vcov.R index 194884d26..ac90ab4b5 100644 --- a/R/sanitize_vcov.R +++ b/R/sanitize_vcov.R @@ -44,7 +44,7 @@ sanitize_vcov <- function(vcov, models, ...) { sandwich_types <- c( "Andrews", - "bootstrap", + "BS", "classical", "constant", "CR", @@ -69,6 +69,8 @@ sanitize_vcov <- function(vcov, models, ...) { "outer-product", "panel-corrected", "PL", + "bootstrap", + "residual", "robust", "stata", "weave", @@ -168,7 +170,6 @@ sanitize_vcov <- function(vcov, models, ...) { } else if (identical(tolower(vcov[[i]]), "bootstrap")) { assert_dependency("sandwich") - vcov[[i]] <- sandwich::vcovBS names(vcov)[i] <- "Bootstrap" } else if (identical(tolower(vcov[[i]]), "panel-corrected")) { diff --git a/R/sanity_checks.R b/R/sanity_checks.R index abb868020..11782fcc2 100644 --- a/R/sanity_checks.R +++ b/R/sanity_checks.R @@ -104,6 +104,9 @@ sanitize_estimate <- function(estimate, number_of_models) { out <- rep(estimate, number_of_models) out <- as.list(out) } else { + if (!is.null(names(estimate)) && length(unique(names(estimate))) > 1) { + insight::format_error("The `estimate` vector must have no name or every element must be named the same.") + } out <- as.list(estimate) } @@ -130,8 +133,8 @@ sanity_coef <- function(coef_map, coef_rename, coef_omit) { checkmate::check_numeric(coef_omit) ) - if ((!isFALSE(coef_rename) && !is.null(coef_rename)) && !is.null(coef_map)) { - stop("coef_map and coef_rename cannot be used together.") + if ((!isTRUE(checkmate::check_flag(coef_rename)) && !is.null(coef_rename)) && !is.null(coef_map)) { + stop("coef_map and coef_rename cannot be used together.", call. = FALSE) } if (!is.null(coef_map)) { @@ -318,4 +321,4 @@ sanity_dots <- function(model, ...) { insight::format_warning(msg) } } -} \ No newline at end of file +} diff --git a/R/update_modelsummary.R b/R/update_modelsummary.R index 3167cff93..7e060ad36 100644 --- a/R/update_modelsummary.R +++ b/R/update_modelsummary.R @@ -16,7 +16,8 @@ update_modelsummary <- function(source = "development") { utils::install.packages("parameters", repos = repo_easystats) utils::install.packages("performance", repos = repo_easystats) utils::install.packages("modelsummary", repos = repo_vab) + utils::install.packages("tinytable", repos = repo_vab) msg <- "Please restart your R session" msg <- c("", strrep("#", nchar(msg)), msg, strrep("#", nchar(msg))) insight::format_alert(msg) -} \ No newline at end of file +} diff --git a/R/utils_labels.R b/R/utils_labels.R index 4f5d2d392..fb0b17ecc 100644 --- a/R/utils_labels.R +++ b/R/utils_labels.R @@ -33,6 +33,11 @@ get_variable_labels_data <- function(data) { if (length(lab) == 0) { lab <- NULL } + for (n in names(lab)) { + if (is.null(lab[[n]])) { + lab[[n]] <- names(n) + } + } return(lab) } @@ -65,4 +70,4 @@ strip_labels <- function(data) { attr(data[[x]], "label") <- NULL } return(data) -} \ No newline at end of file +} diff --git a/altdoc/custom.scss b/altdoc/custom.scss index bba7b4f84..0be1c221f 100644 --- a/altdoc/custom.scss +++ b/altdoc/custom.scss @@ -14,8 +14,6 @@ $sidebar-hl: #5e7ca1; $toc-color: #222; $toc-hl: #5e7ca1; -$navbar-padding-y: .1rem !default; - .table { font-size: .8em; -} \ No newline at end of file +} diff --git a/altdoc/pkgdown.yml b/altdoc/pkgdown.yml new file mode 100644 index 000000000..4e239856c --- /dev/null +++ b/altdoc/pkgdown.yml @@ -0,0 +1,3 @@ +urls: + reference: https://modelsummary.com/man + article: https://modelsummary.com/vignettes \ No newline at end of file diff --git a/altdoc/quarto_website.yml b/altdoc/quarto_website.yml index caa9d2a7d..aabe28d59 100644 --- a/altdoc/quarto_website.yml +++ b/altdoc/quarto_website.yml @@ -1,5 +1,6 @@ project: type: website + output-dir: ../docs/ website: title: "modelsummary: Data and Model Summaries in R" @@ -84,6 +85,6 @@ format: theme: - flatly - custom.scss - highlight-style: nord + code-link: true code-copy: true code-overflow: scroll diff --git a/docs/CITATION.html b/docs/CITATION.html new file mode 100644 index 000000000..8e78bb59e --- /dev/null +++ b/docs/CITATION.html @@ -0,0 +1,815 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – citation + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Citation

+
To cite modelsummary in publications use:
+
+  Arel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.”
+  _Journal of Statistical Software_, *103*(1), 1-23.
+  doi:10.18637/jss.v103.i01 <https://doi.org/10.18637/jss.v103.i01>.
+
+A BibTeX entry for LaTeX users is
+
+  @Article{,
+    title = {{modelsummary}: Data and Model Summaries in {R}},
+    author = {Vincent Arel-Bundock},
+    journal = {Journal of Statistical Software},
+    year = {2022},
+    volume = {103},
+    number = {1},
+    pages = {1--23},
+    doi = {10.18637/jss.v103.i01},
+  }
+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/LICENSE.html b/docs/LICENSE.html new file mode 100644 index 000000000..0da2a8abf --- /dev/null +++ b/docs/LICENSE.html @@ -0,0 +1,1015 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – license + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

License

+
+

GNU General Public License

+

Version 3, 29 June 2007
+Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>

+

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

+
+
+

Preamble

+

The GNU General Public License is a free, copyleft license for software and other kinds of works.

+

The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program–to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.

+

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.

+

To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.

+

For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

+

Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.

+

For the developers’ and authors’ protection, the GPL clearly explains that there is no warranty for this free software. For both users’ and authors’ sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.

+

Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users’ freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.

+

Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.

+

The precise terms and conditions for copying, distribution and modification follow.

+
+
+

Terms and Conditions

+
+

0. Definitions

+

“This License” refers to version 3 of the GNU General Public License.

+

“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.

+

“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.

+

To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.

+

A “covered work” means either the unmodified Program or a work based on the Program.

+

To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.

+

To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.

+

An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.

+
+
+

1. Source Code

+

The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.

+

A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.

+

The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.

+

The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.

+

The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.

+

The Corresponding Source for a work in source code form is that same work.

+
+
+

2. Basic Permissions

+

All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.

+

You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.

+

Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.

+
+ +
+

4. Conveying Verbatim Copies

+

You may convey verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.

+

You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.

+
+
+

5. Conveying Modified Source Versions

+

You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:

+
    +
  • a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
  • +
  • b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
  • +
  • c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
  • +
  • d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
  • +
+

A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation’s users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.

+
+
+

6. Conveying Non-Source Forms

+

You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:

+
    +
  • a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
  • +
  • b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
  • +
  • c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
  • +
  • d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
  • +
  • e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
  • +
+

A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.

+

A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.

+

“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.

+

If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).

+

The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.

+

Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.

+
+
+

7. Additional Terms

+

“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.

+

When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.

+

Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:

+
    +
  • a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
  • +
  • b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
  • +
  • c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
  • +
  • d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
  • +
  • e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
  • +
  • f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
  • +
+

All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.

+

If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.

+

Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.

+
+
+

8. Termination

+

You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).

+

However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.

+

Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.

+

Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.

+
+
+

9. Acceptance Not Required for Having Copies

+

You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.

+
+
+

10. Automatic Licensing of Downstream Recipients

+

Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.

+

An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party’s predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.

+

You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.

+
+
+

11. Patents

+

A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor’s “contributor version”.

+

A contributor’s “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.

+

Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor’s essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.

+

In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.

+

If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient’s use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.

+

If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.

+

A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.

+

Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.

+
+
+

12. No Surrender of Others’ Freedom

+

If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.

+
+
+

13. Use with the GNU Affero General Public License

+

Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.

+
+
+

14. Revised Versions of this License

+

The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

+

Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.

+

If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Program.

+

Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.

+
+
+

15. Disclaimer of Warranty

+

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+
+
+

16. Limitation of Liability

+

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

+
+
+

17. Interpretation of Sections 15 and 16

+

If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.

+

END OF TERMS AND CONDITIONS

+
+
+
+

How to Apply These Terms to Your New Programs

+

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

+

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.

+
<one line to give the program's name and a brief idea of what it does.>
+Copyright (C) 2019 Vincent Arel-Bundock
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+

Also add information on how to contact you by electronic and paper mail.

+

If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:

+
modelsummary Copyright (C) 2019 Vincent Arel-Bundock
+This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type 'show c' for details.
+

The hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, your program’s commands might be different; for a GUI interface, you would use an “about box”.

+

You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>.

+

The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/NEWS.html b/docs/NEWS.html new file mode 100644 index 000000000..808480aaf --- /dev/null +++ b/docs/NEWS.html @@ -0,0 +1,1518 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – news + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

News

+
+

Development

+

New features:

+
    +
  • modelsummary() gets a gof_function argument which accepts functions to extract custom information from models.
  • +
+

datasummary_balance():

+
    +
  • formula can now include variables on the left-hand side to indicate the subset of columns to summarize: datasummary_balance(mpg + hp ~ am, data = mtcars) Thanks to @etiennebacher for feature request #751.
  • +
+

Bugs:

+
    +
  • escape argument not respected in datasummary_df(). Thanks to @adamaltmejd for report #740
  • +
  • datasummary_correlation() supports data.table. Thanks to volatilehead on Twitter for report #737.
  • +
  • Accepts named estimate argument when using shape and statistics are horizontal. Thanks to @iago-pssjd for report #745.
  • +
  • Labelled values but no label for variable broke datasummary(). Thanks to @marklhc for report #752.
  • +
  • coef_map does not work when there is a group. Thanks to @mccarthy-m-g for report #757.
  • +
+
+
+

2.0.0

+

MAJOR BREAKING CHANGE: The default output format is now tinytable instead of kableExtra. Learn more about tinytable here:

+

https://vincentarelbundock.github.io/tinytable/

+

To revert to the previous behavior persistently, users can call:

+

library(modelsummary) config_modelsummary(factory_default = “kableExtra”)

+

Other breaking changes:

+
    +
  • The statistic_override argument was replaced by vcov over 1 year ago, with appropriate deprecation warnings. It is now fully removed.
  • +
  • The group argument was replaced by shape several releases ago. It is now fully removed.
  • +
  • datasummary_skim() +
      +
    • histograms are only available with the tinytable backend. This allows a lot of code simplification and more customization.
    • +
    • The order of arguments type and output is switched for consistency with other functions.
    • +
    • histogram argument is deprecated.
    • +
  • +
+

New features:

+
    +
  • datasummary_skim(): +
      +
    • New type="all" by default to display both numeric and categorical variables in a single table with distinct panels. This feature is only available with the tinytable backend (default).
    • +
    • by argument allows summarizing numeric variables by group.
    • +
    • fun_numeric argument accepts a list of functions to control the summary columns.
    • +
  • +
  • modelsummary(): +
      +
    • statistic and estimate can be specified as named vectors to control the names of statistics when displayed in different columns using the shape argument. (Thanks to @mps9506 for bug report #722)
    • +
    • modelsummary(panels, shape = "cbind") automatically adds column-spanning labels when panels is a named nested list of models.
    • +
  • +
  • config_modelsummary() gets a startup_message argument to silence the startup message persistently.
  • +
  • Improved documentation and vignettes, providing clearer instructions and examples.
  • +
  • Updated tests and snapshots to ensure reliability and consistency across changes.
  • +
+

Bug fixes:

+
    +
  • Fixed Issue #399: datasummary_balance() siunitx formatting.
  • +
  • Fixed Issue #782: Useless warning in some modelplot() calls. Thanks to @iago-pssjd for the report and @florence-laflamme for the fix.
  • +
  • Addressed various bugs and made optimizations for better performance and user experience.
  • +
+
+
+

1.4.5

+
    +
  • tinytable supports histograms in datasummary_skim()
  • +
  • config_modelsummary() supports tinytable factory.
  • +
+
+
+

1.4.4

+
    +
  • Support the tinytable package as an output format (“factory”): https://vincentarelbundock.github.io/tinytable/
  • +
  • Quarto: md output format is recognized.
  • +
  • options(modelsummary_factory_default) is respected, even in qmd->md documents.
  • +
+

Bugs:

+
    +
  • Some omitted coefficients with I() operator in formulas. Issue #693.
  • +
+
+
+

1.4.3

+

Misc:

+
    +
  • Duplicate values in shape groups are removed automatically for cleaner labels.
  • +
  • “Title” line no longer indented in markdown tables. Thanks to Ryan Briggs for report #671.
  • +
+

Bugs:

+
    +
  • Small p values were not displayed properly in HTML output using kableExtra. Issue #669.
  • +
+
+
+

1.4.2

+

New:

+
    +
  • Minimal support for Typst output, with auto-detection in Quarto documents.
  • +
  • strip argument in dvnames.
  • +
  • s.value statistic is now available whenever p.value is available. See Greenland (2019).
  • +
  • datasummary_skim() now includes histograms in gt tables.
  • +
+

Bugs:

+
    +
  • GOF term names get escaped in LaTeX. Thanks to @shreyasgm for reviving Issue #546.
  • +
  • Conflict with furrr generated errors for some models. Thanks to @sammo3182 for Issue #647.
  • +
+
+
+

1.4.1

+

New:

+
    +
  • fmt_sci() can now be used in the fmt argument for rounding with scientific notation.
  • +
+

Bugs:

+
    +
  • Group separators respect add_rows with shape="rbind". Thanks to @lrose1 for Report #626.
  • +
  • Bad column with horizontal models in shape and grouped estimates. Thanks to @iago-pssjd for Report #631.
  • +
  • coef_rename=TRUE bug with grouped estimates. Thanks to @iago-pssjd for Report #631.
  • +
  • Upstream issue #881 in parameters meant that vcov was no longer used for confidence intervals.
  • +
+
+
+

1.4.0

+
    +
  • Built-in support for markdown tables.
  • +
  • Package no longer depends on kableExtra. Recommends an additional install for other formats.
  • +
  • Persistent configuration of default output format: config_modelsummary(factory_default = "gt")
  • +
  • shape = "rcollapse" and shape = "rbind"
  • +
  • glance_custom() can drop GOF by assigning NA: https://stackoverflow.com/questions/75215355/assigning-different-coefficient-names-and-goodness-of-fit-statistics-to-differen
  • +
  • When a statistic is not available, modelsummary prints an empty cell instead of returning an error.
  • +
  • “\label{tab:something}” works in title even when escape=TRUE
  • +
  • Multiple fixest_multi objects supported.
  • +
  • options(modelsummary_future = FALSE) disables future parallelism.
  • +
+

Bug fixes:

+
    +
  • statistic=NULL is now respected when shape="rbind". Thanks to Panos Mavros for report #620.
  • +
  • get_estimates() supports vcov string shortcuts and formulas. Thanks to @ethans-carl for report #605.
  • +
  • Quarto and Rmarkdown documents include situnix in header automatically for decimal alignement with align="ddd"
  • +
  • escape is now respected by modelsummary with shape="rbind". Thanks to @chickymonkeys for report #622.
  • +
+
+
+

1.3.0

+

Breaking change:

+
    +
  • The default column label style in modelsummary() has changed from “Model 1” to “(1)”. The benefits are: labels are no longer in English by default; use less horizontal space; eliminate the “Model” redundancy. Unfortunately, this could break code in some edge cases where users rely on column names to manipulate tables. The old behavior can be restored by calling: options(modelsummary_model_labels="model")
  • +
+

New features:

+
    +
  • shape="rbind" to stack multiple regression tables and create “panels” with labelled groups of models.
  • +
  • fmt: new helper functions for different formatting styles +
      +
    • fmt = fmt_decimal(2): decimal digits
    • +
    • fmt = fmt_decimal(digits = 2, pdigits = 4): decimal digits with p value-specific setting
    • +
    • fmt = fmt_sprintf("%.3f"): sprintf() decimal
    • +
    • fmt = fmt_sprintf("%.3e"): sprintf() scientific
    • +
    • fmt = fmt_significant(3): significant digits
    • +
    • fmt = fmt_statistic("estimate" = 2, "std.error" = 3): statistic-specific formatting
    • +
    • fmt = fmt_term("(Intercept)" = 2, "hp" = 3): term-specific formatting
    • +
    • fmt = fmt_identity(): raw values
    • +
  • +
  • New styles for default column labels in modelsummary, such as Roman Numerals or letters in parentheses. +
      +
    • Set the style with a global option: options(modelsummary_model_labels = "roman")
    • +
    • Supported styles: “model”, “arabic”, “letters”, “roman”, “(arabic)”, “(letters)”, “(roman)””
    • +
  • +
  • modelplot(draw = FALSE) now returns a p.value column. This allows conditional aesthetics (see the modelplot vignette).
  • +
  • Better integration with the marginaleffects package.
  • +
+

Bugs:

+
    +
  • Some fixest models returns useless “group.x” and “group.y” columns. Isse #591. Thanks to Adam Altmejd for the report.
  • +
+
+
+

1.2.0

+

Breaking change:

+
    +
  • With the shape and output="dataframe" arguments, there always used to be a group column. Now, this column has the same name as the variable in the shape formula (“response”, “component”, etc.).
  • +
+

New features:

+
    +
  • shape can include multiple groups.
  • +
  • coef_rename can be an unnamed vector of length equal to the number of terms in the final table, obtained after coef_map and coef_omit are applied and models are merged.
  • +
  • coef_omit accepts numeric indices. Positive values: coefficients to omit. Negative values: coefficients to keep.
  • +
  • datasummary_skim: Increased maximum number of variables to 250.
  • +
  • Quarto notebooks compile to Word and Markdown automatically.
  • +
+

Bug fixes:

+
    +
  • Order of notes preserved in some output format (Issue #577)
  • +
+
+
+

1.1.0

+

Breaking change:

+
    +
  • Requires siunitx version 3.0.25 LaTeX package.
  • +
  • The title argument now respects the escape argument for all kableExtra output formats. This can break tables in which users manually escaped titles.
  • +
+

New features:

+
    +
  • “d” is accepted for decimal-alignment in the align argument for all output formats. modelsummary(mod, align = "ld")
  • +
  • New update_modelsummary() function makes it easy to install the dev versions of modelsummary and its dependencies (mostly useful for Vincent and people who report bugs).
  • +
  • Rounding: display at least one significant digit by default.
  • +
  • Automatic renaming of haven labels in modelsummary(), datasummary(), datasummary_skim()
  • +
  • Allow output = "filename.csv"
  • +
  • Allow output = "filename.xlsx"
  • +
  • add_columns argument supported in modelsummary()
  • +
  • datasummary_balance supports the stars argument.
  • +
  • Allow stars and confidence intervals with align = "d" column.
  • +
+

Bug fixes:

+
    +
  • In some locales, the HTML minus sign created problems in the output. We only use it in “known” locales.
  • +
  • Many minor bug fixes
  • +
+
+
+

1.0.2

+
    +
  • Minor release to fix CRAN failure
  • +
+
+
+

1.0.1

+
    +
  • shape argument accepts interactions with the colon “:” character. This combines two columns into one, which can be useful to display terms and group names in a single column.
  • +
  • Parallelization using parallel::mclapply. See ?modelsummary
  • +
  • modelsummary no longer computes confidence intervals when not necessary, which can save some time. Also see: conf_level=NULL
  • +
  • Added log likelihood to GOF for lm and glm models.
  • +
  • Removed extraneous warnings
  • +
  • Bug fixes
  • +
+
+
+

1.0.0

+

This first major release accompanies the publication of an article in the Journal of Statistical Software:

+

Arel-Bundock, Vincent (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. doi:10.18637/jss.v103.i01 https://doi.org/10.18637/jss.v103.i01.’

+

If you like modelsummary, please cite the JSS article and tell your friends about it.

+

Minor changes:

+
    +
  • gof_map="all" includes all available statistics. gof_map="none" excludes all statistics.
  • +
  • Bug fixes
  • +
+
+
+

0.11.1

+
    +
  • Better printout for term names in mixed-effects models
  • +
  • {brms} and {stanreg} models now extracted with diagnostic=NULL and test=NULL by default for speed.
  • +
+
+
+

0.11.0

+

Breaking changes:

+
    +
  • modelsummary_wide is no longer available. Use the shape argument of modelsummary instead.
  • +
  • modelsummary now uses the easystats packages (performance and parameters) to extract estimates and goodness-of-fit statistics instead of broom. This can be reverted by setting a global option: options(modelsummary_get="broom"). This change aims to (1) increase consistency across models, (2) improve the developers’ ability to push bug fixes upstream when necessary, and (3) improve support for mixed effects, bayesian, and GAM models. The two main drawbacks are: (a) The set of printed statistics may be slightly different from previous versions of modelsummary (b) The group identifiers used in the shape formula will also be different for certain models (e.g., in nnet::multinom, y.level becomes response).
  • +
+

New features:

+
    +
  • The shape argument accepts a formula and can reshape information in myriad ways. Deprecates the group argument. Examples: +
      +
    • ~ statistic: statistics are shown horizontally in distinct columns.
    • +
    • model ~ term: models in rows and terms in columns.
    • +
    • term + y.level + statistic ~ model: grouped coefficients for multivariate outcome in nnet::multinom
    • +
    • y.level ~ model: partial match is the same as the previous formula
    • +
  • +
  • Format distinct statistics differently by passing a named list to fmt: +
      +
    • modelsummary(mod, fmt = list(estimate = 2, std.error = 1, rmse = 4))
    • +
  • +
  • Use glue to apply functions to numeric values by setting fmt = NULL. Example: +
      +
    • modelsummary(model, fmt = NULL, estimate = "{log(estimate)}")
    • +
  • +
  • Update for breaking changes after fixest 0.10.4
  • +
+

Bug fixes:

+
    +
  • group_map rename issue
  • +
  • Residual standard error mistakenly labelled “RMSE” in lm models.
  • +
  • datasummary_skim output to jpg should now works
  • +
  • escape fixes
  • +
+
+
+

0.10.0

+
    +
  • New exponentiate argument for modelsummary() and modelplot()
  • +
  • gof_map accepts a vector such as c("rmse", "nobs", "r.squared")
  • +
  • Drop rlang dependency
  • +
  • Bug fixes
  • +
+
+
+

0.9.6

+

datasummary_balance:

+
    +
  • Accepts ~ 1 as a formula to summarize all data.
  • +
+

Misc:

+
    +
  • documentation improvements
  • +
  • RMSE included by default in models of class lm
  • +
+
+
+

0.9.5

+

modelsummary:

+
    +
  • vcov strings like HC1 and Robust are now case-insensitive
  • +
  • gof_map now accepts a data.frame or tibble with a fmt list-column which includes functions (see Examples in docs)
  • +
  • R2 is no longer computed by default for bayesian and mixed effects models. An informative one-time warning is printed about the metrics argument.
  • +
+

datasummary_skim:

+
    +
  • Histograms now work in Jupyter
  • +
  • Bugfix: harmless error message is no longer printed
  • +
+

kableExtra factory:

+
    +
  • The col.names argument can now be passed to kableExtra::kbl through the … ellipsis.
  • +
+

Misc:

+
    +
  • Many small improvements to the vignettes and docs
  • +
  • output = "github_document" is now supported
  • +
+
+
+

0.9.4

+
    +
  • Bug fix: siunitx and rounding NA
  • +
+
+
+

0.9.3

+

modelsummary:

+
    +
  • F statistic takes into account vcov argument
  • +
  • Support group = group ~ model + term
  • +
+

datasummary_balance:

+
    +
  • Weighted means and standard deviations are now supported. Counts and percentages are not, but raise a warning.
  • +
+

Misc:

+
    +
  • Bugfix: rounding in LaTeX w/ siunitx and NaN entries.
  • +
  • output=‘jupyter’ no longer prints an extraneous TRUE to the notebook
  • +
+
+
+

0.9.2

+

modelsummary:

+ +

datasummary_correlation:

+
    +
  • add_rows and add_columns arguments are now available here.
  • +
+

Misc:

+
    +
  • Global options for output factories are renamed: modelsummary_factory_default, modelsummary_factory_html, etc.
  • +
  • Hot fix for change in R-devel behavior or intersect
  • +
+

Bug fixes:

+
    +
  • datasummary_balance: escape variable names when escape=TRUE
  • +
  • Blogdown LaTeX dependency bug when output is HTML
  • +
+
+
+

0.9.1

+

Breaking change:

+
    +
  • Support for dcolumn for dot-aligned columns is deprecated. Use “d” in the align argument instead.
  • +
+

Other changes:

+
    +
  • LaTeX output: Numeric entries are wrapped in the \num{} function from the siunitx package by default. This produces much nicer formatting. This can be disabled with a global option. See ?modelsummary
  • +
  • The align argument accepts a “d” column for dot-alignment using the siunitx LaTeX package: align="ldd".
  • +
  • HTML tables display proper minus signs.
  • +
  • New escape argument in most table-building functions.
  • +
  • LaTeX output accepts the threeparttable=TRUE argument through ...
  • +
  • No more dependency on tidyr
  • +
+

modelsummary:

+
    +
  • group: The order of terms in the formula determines the order of rows/columns
  • +
+

modelsummary_wide:

+
    +
  • Note: This function will eventually be deprecated
  • +
  • Bugfix with statistic=NULL.
  • +
+

modelplot:

+
    +
  • Preserves order of models in the user-supplied list
  • +
+

datasummary_crosstab:

+
    +
  • statistic=NULL produces a very basic crosstab
  • +
+

datasummary_crosstab:

+
    +
  • Default alignment “lrrrrr” consistent with other datasummary_* functions
  • +
+
+
+

0.8.1

+

modelsummary:

+
    +
  • Disable stars footnote with options("modelsummary_stars_note" = FALSE)
  • +
  • longtable=TRUE works for LaTeX output
  • +
  • Interactions with “:” are no longer converted to “x” when coef_map or coef_rename are used.
  • +
  • group = model ~ term + group is now supported.
  • +
+

datasummary_skim:

+
    +
  • datasummary_skim("categorical") keeps NA by default. Users can convert variables to factors before calling datasummary_skim to exclude NA.
  • +
+

Other:

+
    +
  • Improved warnings for bad calls: modelsummary(model1, model2)
  • +
  • gt titles use the new caption argument in the gt 0.3.0 function
  • +
  • Bug fix: Overaggressive tests for glue strings prevented functions inside {}
  • +
+
+
+

0.8.0

+

Breaking change:

+
    +
  • The default significance markers stars=TRUE have been updated to be consistent with the default output from base R (e.g., in summary.lm). The new significance thresholds are: “+” p < 0.1, “” p < 0.05, ”” p < 0.01, ”” p < 0.001
  • +
+

datasummary_crosstab:

+
    +
  • New function to produce cross-tabulations
  • +
+

datasummary:

+
    +
  • N is smart enough to return either the number of elements in a subset or the number of non-missing observations in a variable
  • +
+

datasummary_balance:

+
    +
  • Keeps NAs in factor variables by default. Users can convert their variables with the factor() function to omit NAs automatically.
  • +
+

modelsummary:

+
    +
  • themes can be set using global options (experimental)
  • +
  • new vcov options: “bootstrap”, “HAC”, “NeweyWest”, “Andrews”, “panel-corrected”, “weave”, “outer-product”
  • +
  • A valid get_gof (glance) is now optional.
  • +
  • … is pushed through to sandwich, which allows things like: modelsummary(model, vcov = "bootstrap", R = 1000, cluster = "firm")
  • +
+

Other:

+
    +
  • Jupyter notebook support via output="jupyter"
  • +
  • Bug fixes
  • +
+
+
+

0.7.0

+

modelsummary:

+
    +
  • new arguments for modelsummary: group and group_map for grouped parameters (e.g., outcome levels in multinomial logit or components of gamlss model).
  • +
  • dvnames() makes it easy to get dependent variable column titles (thanks to @NickCH-K)
  • +
  • output="modelsummary_list" to save a lightweight list-based representation of the table which can be saved and fed to modelsummary once more to get a full table.
  • +
  • vcov adds a row to note the type of standard errors.
  • +
  • modelsummary accepts a single model with multiple vcovs.
  • +
  • get_gof forwards … to model_performance
  • +
  • coef_map accepts unnamed vectors for easy subsetting
  • +
  • fixest::fixest_multi support
  • +
  • options(modelsummary_get) to set the order of extraction functions to use under the hood (broom vs. easystats vs. all)
  • +
  • metrics argument of performance::model_performance is available via modelsummary’s … ellipsis to limit the GOF statistics in Bayesian models.
  • +
  • users can omit the stars legend note by using glue strings: estimate="{estimate}{stars}"
  • +
  • output=“html” can use gt by setting options(modelsummary_factory_html="gt")
  • +
+

datasummary_correlation:

+
    +
  • passes ... forward
  • +
  • new function: datasummary_correlation_format
  • +
  • datasummary_correlation’s method argument accepts functions and “pearspear” (thanks to @joachim-gassen)
  • +
+

datasummary:

+
    +
  • datasummary functions and rounding accept …, big.mark, etc.
  • +
+

datasummary_skim:

+
    +
  • now works with haven_labeled numeric
  • +
  • faster tables with bayesian models.
  • +
+

Bug fixes and lints

+
+
+

0.6.6

+
    +
  • new output format: latex_tabular
  • +
  • tidy_custom allows partial term matches
  • +
  • modelsummary(coef_rename) accepts functions
  • +
  • new function coef_rename for use in modelsummary(coef_rename=coef_rename)
  • +
  • modelplot accepts add_rows to add reference categories
  • +
  • informative error message when estimate or statistic is not available
  • +
  • bug fixes
  • +
+
+
+

0.6.5

+
    +
  • statistic_override becomes vcov
  • +
  • vcov accepts shortcuts: “robust”, “stata”, “HC0”, etc.
  • +
  • vcov accepts formulas for clustered SEs: ~group
  • +
  • modelsummary_wide has a new “stacking” argument
  • +
  • html horizontal rule to separate estimates form gof
  • +
  • gof_map accepts list of lists. only needs 3 columns.
  • +
  • support officedown Rmd
  • +
  • estimate accepts a vector for per model estimates
  • +
  • options(modelsummary_default) can be markdown, html, latex
  • +
  • bug: passing arguments through …
  • +
  • bug: stars and rounding
  • +
+
+
+

0.6.4

+
    +
  • glue format for estimate and statistic
  • +
  • easystats support for model info extraction
  • +
  • deprecate statistic_vertical
  • +
  • deprecate extract_models. Use modelsummary(output=“dataframe”) instead.
  • +
  • modelplot pushes … through to modelsummary(output=“dataframe”)
  • +
  • datasummary_skim(type=“dataset”)
  • +
  • gof_map omits by default
  • +
  • datasummary_balance uses row percentages
  • +
  • statistic_override does not require a list
  • +
  • statistic_override accepts a single model
  • +
  • N function for well formatted N in datasummary
  • +
  • Bug fixes
  • +
+
+
+

0.6.3

+
    +
  • new function: modelsummary_wide
  • +
  • coef_omit and gof_omit use grepl(perl=TRUE)
  • +
  • fmt accepts integer, string or function and respects options(OutDec=“,”)
  • +
  • align argument for modelsummary
  • +
  • align is more liberal to accept dcolumn alignment
  • +
  • glance_custom methods for lfe and fixest
  • +
  • bug fixes
  • +
+
+
+

0.6.2

+
    +
  • new argument: coef_rename
  • +
  • new function: datasummary_df
  • +
  • preserve term order in modelsummary
  • +
  • refactor datasummary_balance
  • +
  • datasummary_skim uses svg histograms instead of unicode
  • +
  • removed 5 dependencies
  • +
  • pass … to kableExtra::kbl for more customization
  • +
  • test improvements
  • +
  • internal code style
  • +
  • bug fixes
  • +
+
+
+

0.6.1

+
    +
  • bug fixes
  • +
+
+
+

0.6.0

+
    +
  • default HTML output factory is now kableExtra
  • +
  • interaction “:” gsubbed by “0d7”
  • +
  • dependencies: removed 1 depends, 3 imports, and 3 suggests
  • +
  • word_document knitr works out-of-the-box
  • +
  • bug fixes
  • +
+
+
+

0.5.1

+
    +
  • glance_custom.fixest ships with modelsummary
  • +
+
+
+

0.5.0

+
    +
  • datasummary
  • +
  • datasummary_skim
  • +
  • datasummary_balance
  • +
  • datasummary_correlation
  • +
  • modelplot
  • +
  • allow duplicate model names
  • +
  • bug: can’t use coef_map with multiple statistics (thanks @sbw78)
  • +
  • bug: wrong number of stars w/ statistic=‘p.value’ (thanks @torfason)
  • +
  • output=‘data.frame’. extract is no longer documented.
  • +
+
+
+

0.4.1

+
    +
  • add_rows now accepts a data.frame with “position” and “section” columns
  • +
  • add_rows_location is deprecated
  • +
  • bug in sanity_output prevented overwriting files
  • +
+
+
+

0.4.0

+
    +
  • huxtable support
  • +
  • flextable support
  • +
  • estimate argument
  • +
  • fixest tidiers
  • +
  • website and vignette improvements
  • +
  • gof_map additions
  • +
  • glance_custom
  • +
  • tidy_custom
  • +
+
+
+

0.3.0

+
    +
  • Out-of-the-box Rmarkdown compilation to HTML, PDF, RTF
  • +
  • kableExtra output format for LaTeX and Markdown
  • +
  • Support for threeparttable, colors, and many other LaTeX options
  • +
  • Deprecated arguments: filename, subtitle
  • +
  • Deprecated functions: clean_latex, knit_latex
  • +
  • pkgdown website and doc improvements
  • +
  • mitools tidiers
  • +
  • New tests
  • +
+
+
+

0.2.1

+
    +
  • Convenience function to render markdown in row/column labels
  • +
  • bug: breakage when all GOF were omitted
  • +
  • Clean up manual with @keywords internal
  • +
  • bug: tidyr import
  • +
+
+
+

0.2.0

+
    +
  • gt is now available on CRAN
  • +
  • new latex_env argument for knit_latex and clean_latex
  • +
  • bug when all gof omitted
  • +
  • bug in statistic_override with functions
  • +
  • bug caused by upstream changes in tab_style
  • +
  • bug caused by upstream changes in filename=‘rtf’
  • +
  • Allow multiple rows of uncertainty estimates per coefficient
  • +
  • Preserve add_rows order
  • +
  • Display uncertainty estimates next to the coefficient with statistic_vertical = FALSE
  • +
  • Better clean_latex function
  • +
  • Can display R2 and confidence intervals for mice-imputed lm-models
  • +
  • Internal functions have @keywords internal to avoid inclusion in docs
  • +
  • Statistic override accepts pre-formatted character vectors
  • +
+
+
+

0.1.0

+
    +
  • Initial release (gt still needs to be installed from github)
  • +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/custom.scss b/docs/custom.scss new file mode 100644 index 000000000..0be1c221f --- /dev/null +++ b/docs/custom.scss @@ -0,0 +1,19 @@ +/*-- scss:defaults --*/ +@import url(http://fonts.googleapis.com/css?family=Lato|Roboto|Open+Sans:400italic,700italic,400,700); +@import url(http://fonts.googleapis.com/css?family=Source+Code+Pro:400italic,700italic,400,700); +$font-family-sans-serif: 'Lato'; + +$body-color: #222 !default; +$link-color: #5e7ca1; +$code-color: #222; +$navbar-bg: #ececec; +$navbar-fg: #222; +$navbar-hl: #5e7ca1; +$sidebar-fg: #222; +$sidebar-hl: #5e7ca1; +$toc-color: #222; +$toc-hl: #5e7ca1; + +.table { + font-size: .8em; +} diff --git a/docs/figures/gallery/gallery.sh b/docs/figures/gallery/gallery.sh new file mode 100755 index 000000000..925e6c5a5 --- /dev/null +++ b/docs/figures/gallery/gallery.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Define the output GIF filename +output_gif="modelsummary_gallery.gif" + +# Use ImageMagick to create an animated GIF from images starting with 'tinytable_gallery_' +# -delay is increased for a slower animation (e.g., 100 equals 1 second per frame) +# -resize option is used to fit images within a 1280x720 frame (16:9 aspect ratio) +# convert -delay 250 -loop 0 tinytable_gallery_*.png -resize 1250x690 -gravity center -extent 1280x720 "$output_gif" +# convert -delay 250 -loop 0 tinytable_gallery_*.png -resize 1000x500 -gravity center -extent 1025x576 "$output_gif" +convert -delay 400 -loop 0 gallery_*.png -resize 1000x500 -gravity center -extent 1025x576 -layers Optimize -colors 128 "$output_gif" + +# Display a message when done +echo "Animated GIF created: $output_gif" diff --git a/docs/figures/gallery/gallery_00.png b/docs/figures/gallery/gallery_00.png new file mode 100644 index 000000000..408883e52 Binary files /dev/null and b/docs/figures/gallery/gallery_00.png differ diff --git a/docs/figures/gallery/gallery_01.png b/docs/figures/gallery/gallery_01.png new file mode 100755 index 000000000..15768abc7 Binary files /dev/null and b/docs/figures/gallery/gallery_01.png differ diff --git a/docs/figures/gallery/gallery_02.png b/docs/figures/gallery/gallery_02.png new file mode 100755 index 000000000..8c5fbe817 Binary files /dev/null and b/docs/figures/gallery/gallery_02.png differ diff --git a/docs/figures/gallery/gallery_03.png b/docs/figures/gallery/gallery_03.png new file mode 100755 index 000000000..867455370 Binary files /dev/null and b/docs/figures/gallery/gallery_03.png differ diff --git a/docs/figures/gallery/gallery_04.png b/docs/figures/gallery/gallery_04.png new file mode 100644 index 000000000..b40b2b227 Binary files /dev/null and b/docs/figures/gallery/gallery_04.png differ diff --git a/docs/figures/gallery/gallery_05.png b/docs/figures/gallery/gallery_05.png new file mode 100644 index 000000000..cc21bcbcd Binary files /dev/null and b/docs/figures/gallery/gallery_05.png differ diff --git a/docs/figures/gallery/gallery_06.png b/docs/figures/gallery/gallery_06.png new file mode 100755 index 000000000..33eb4dec4 Binary files /dev/null and b/docs/figures/gallery/gallery_06.png differ diff --git a/docs/figures/gallery/gallery_07.png b/docs/figures/gallery/gallery_07.png new file mode 100644 index 000000000..e6fdb0ff2 Binary files /dev/null and b/docs/figures/gallery/gallery_07.png differ diff --git a/docs/figures/gallery/modelsummary_gallery.gif b/docs/figures/gallery/modelsummary_gallery.gif new file mode 100644 index 000000000..0588247da Binary files /dev/null and b/docs/figures/gallery/modelsummary_gallery.gif differ diff --git a/docs/freeze.rds b/docs/freeze.rds new file mode 100644 index 000000000..2e769542a Binary files /dev/null and b/docs/freeze.rds differ diff --git a/docs/images/modelsummary_montage.png b/docs/images/modelsummary_montage.png new file mode 100755 index 000000000..23b1b6eb8 Binary files /dev/null and b/docs/images/modelsummary_montage.png differ diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..190531667 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,909 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +

+



+

+

modelsummary creates tables and plots to present descriptive statistics and to summarize statistical models in R.

+
+

modelsummary is a package to summarize data and statistical models in R. It supports over one hundred types of models out-of-the-box, and allows users to report the results of those models side-by-side in a table, or in coefficient plots. It makes it easy to execute common tasks such as computing robust standard errors, adding significance stars, and manipulating coefficient and model labels. Beyond model summaries, the package also includes a suite of tools to produce highly flexible data summary tables, such as dataset overviews, correlation matrices, (multi-level) cross-tabulations, and balance tables (also known as “Table 1”). The appearance of the tables produced by modelsummary can be customized using external packages such as kableExtra, gt, flextable, or huxtable; the plots can be customized using ggplot2. Tables can be exported to many output formats, including HTML, LaTeX, Text/Markdown, Microsoft Word, Powerpoint, Excel, RTF, PDF, and image files. Tables and plots can be embedded seamlessly in rmarkdown, knitr, or Sweave dynamic documents. The modelsummary package is designed to be simple, robust, modular, and extensible (Arel-Bundock, 2022).

+
+
+

What?

+

modelsummary includes two families of functions:

+
    +
  1. Model Summary +
      +
    • modelsummary: Regression tables with side-by-side models.
    • +
    • modelplot: Coefficient plots.
    • +
  2. +
  3. Data Summary +
      +
    • datasummary: Powerful tool to create (multi-level) cross-tabs and data summaries.
    • +
    • datasummary_crosstab: Cross-tabulations.
    • +
    • datasummary_balance: Balance tables with subgroup statistics and difference in means (aka “Table 1”).
    • +
    • datasummary_correlation: Correlation tables.
    • +
    • datasummary_skim: Quick overview (“skim”) of a dataset.
    • +
    • datasummary_df: Turn dataframes into nice tables with titles, notes, etc.
    • +
  4. +
+
+
+

Why?

+

Here are a few benefits of modelsummary over some alternative packages:

+
+

Easy

+

modelsummary is very easy to use. This simple call often suffices:

+
library(modelsummary)
+
+mod <- lm(y ~ x, dat)
+

The command above will automatically display a summary table in the Rstudio Viewer or in a web browser. All you need is one word to change the output format. For example, a text-only version of the table can be printed to the Console by typing:

+
modelsummary(mod, output = "markdown")
+

Tables in Microsoft Word and LaTeX formats can be saved to file by typing:

+
modelsummary(mod, output = "table.docx")
+modelsummary(mod, output = "table.tex")
+
+
+

Flexible

+

Information: The package offers many intuitive and powerful utilities to customize the information reported in a summary table. You can rename, reorder, subset or omit parameter estimates; choose the set of goodness-of-fit statistics to include; display various “robust” standard errors or confidence intervals; add titles, footnotes, or source notes; insert stars or custom characters to indicate levels of statistical significance; or add rows with supplemental information about your models.

+

Appearance: Thanks to the tinytable, gt, kableExtra, huxtable, flextable, and DT packages, the appearance of modelsummary tables is endlessly customizable. The appearance customization page shows tables with colored cells, weird text, spanning column labels, row groups, titles, source notes, footnotes, significance stars, and more. This only scratches the surface of possibilities.

+

Supported models: Thanks to the broom and parameters, modelsummary supports hundreds of statistical models out-of-the-box. Installing other packages can extend the capabilities further (e.g., broom.mixed). It is also very easy to add or customize your own models.

+

Output formats: modelsummary tables can be saved to HTML, LaTeX, Text/Markdown, Microsoft Word, Powerpoint, RTF, JPG, or PNG formats. They can also be inserted seamlessly in Rmarkdown documents to produce automated documents and reports in PDF, HTML, RTF, or Microsoft Word formats.

+
+
+

Dangerous

+

modelsummary is dangerous! It allows users to do stupid stuff like inserting squirrels in all your tables.

+

+
+
+

Reliable

+

modelsummary is reliably dangerous! The package is developed using a suite of unit tests with about 95% coverage, so it (probably) won’t break.

+
+
+

Community

+

modelsummary does not try to do everything. Instead, it leverages the incredible work of the R community. By building on top of the broom and parameters packages, modelsummary already supports hundreds of model types out-of-the-box. modelsummary also supports five of the most popular table-building and customization packages: gt, kableExtra, huxtable, flextable, and DT packages. By using those packages, modelsummary allows users to produce beautiful, endlessly customizable tables in a wide variety of formats, including HTML, PDF, LaTeX, Markdown, and MS Word.

+

One benefit of this community-focused approach is that when external packages improve, modelsummary improves as well. Another benefit is that leveraging external packages allows modelsummary to have a massively simplified codebase (relative to other similar packages). This should improve long term code maintainability, and allow contributors to participate through GitHub.

+
+
+
+

How?

+

You can install modelsummary from CRAN:

+
install.packages('modelsummary')
+

You can install the development version of modelsummary and its dependencies from R-Universe:

+
install.packages(
+    c("modelsummary", "tinytable", "insight", "performance", "parameters"),
+    repos = c(
+        "https://vincentarelbundock.r-universe.dev",
+        "https://easystats.r-universe.dev"))
+

Restart R completely before moving on.

+
+
+

Get started

+

The GET STARTED vignette will walk you through the basics of modelsummary.

+

You will find that there are a million ways to customize the tables and plots produced by modelsummary, but the Get Started page only scratches the surface. For details, see the vignettes:

+ + + +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/man/coef_rename.html b/docs/man/coef_rename.html new file mode 100644 index 000000000..4425d4d37 --- /dev/null +++ b/docs/man/coef_rename.html @@ -0,0 +1,1072 @@ + + + + + + +modelsummary: Data and Model Summaries in R – coef_rename + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Rename model terms

+

Description

+

A convenience function which can be passed to the coef_rename argument of the modelsummary function.

+

Usage

+
coef_rename(
+  x,
+  factor = TRUE,
+  factor_name = TRUE,
+  backticks = TRUE,
+  titlecase = TRUE,
+  underscore = TRUE,
+  asis = TRUE
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+x + +character vector of term names to transform +
+factor + +boolean remove the "factor()" label +
+factor_name + +boolean remove the "factor()" label and the name of the variable +
+backticks + +boolean remove backticks +
+titlecase + +boolean convert to title case +
+underscore + +boolean replace underscores by spaces +
+asis + +boolean remove the I from as-is formula calls +

Examples

+
+
library(modelsummary)
+
+library(modelsummary)
+dat <- mtcars
+dat$horse_power <- dat$hp
+mod <- lm(mpg ~ horse_power + factor(cyl), dat)
+modelsummary(mod, coef_rename = coef_rename)
+
+ + + + + +tinytable_068sp7zsk08y3v08zq4i + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)28.650
(1.588)
Horse Power-0.024
(0.015)
6 -5.968
(1.639)
8 -8.521
(2.326)
Num.Obs. 32
R2 0.754
R2 Adj. 0.727
AIC 169.9
BIC 177.2
Log.Lik. -79.948
F 28.585
RMSE 2.94
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/config_modelsummary.html b/docs/man/config_modelsummary.html new file mode 100644 index 000000000..a0456d401 --- /dev/null +++ b/docs/man/config_modelsummary.html @@ -0,0 +1,875 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – config_modelsummary + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Persistent user settings for the modelsummary package

+
+

Description

+

Persistent user settings for the modelsummary package

+
+
+

Usage

+
config_modelsummary(
+  factory_default,
+  factory_latex,
+  factory_html,
+  factory_markdown,
+  startup_message,
+  reset = FALSE
+)
+
+
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+factory_default + +Default output format: "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown" +
+factory_latex + +Name of package used to generate LaTeX output when output=“latex”. +
+factory_html + +Name of package used to generate LaTeX output when output=“html”. +
+factory_markdown + +Name of package used to generate LaTeX output when output=“markdown”. +
+startup_message + +TRUE or FALSE to show warnings at startup +
+reset + +TRUE to return to default settings. +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/datasummary.html b/docs/man/datasummary.html new file mode 100644 index 000000000..e8754eb5d --- /dev/null +++ b/docs/man/datasummary.html @@ -0,0 +1,2382 @@ + + + + + + +modelsummary: Data and Model Summaries in R – datasummary + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Summary tables using 2-sided formulae: crosstabs, frequencies, table 1s and more.

+

Description

+

datasummary can use any summary function which produces one numeric or character value per variable. The examples section of this documentation shows how to define custom summary functions.

+

modelsummary also supplies several shortcut summary functions which can be used in datasummary() formulas: Min, Max, Mean, Median, Var, SD, NPercent, NUnique, Ncol, P0, P25, P50, P75, P100.

+

See the Details and Examples sections below, and the vignettes on the modelsummary website:

+
    +
  • +

    https://modelsummary.com/

    +
  • +
  • +

    https://modelsummary.com/articles/datasummary.html

    +
  • +

Usage

+
datasummary(
+  formula,
+  data,
+  output = "default",
+  fmt = 2,
+  title = NULL,
+  notes = NULL,
+  align = NULL,
+  add_columns = NULL,
+  add_rows = NULL,
+  sparse_header = TRUE,
+  escape = TRUE,
+  ...
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+formula + +A two-sided formula to describe the table: rows ~ columns. See the Examples section for a mini-tutorial and the Details section for more resources. Grouping/nesting variables can appear on both sides of the formula, but all summary functions must be on one side. +
+data + +A data.frame (or tibble) +
+output + +

filename or object type (character string)

+
    +
  • +

    Supported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg

    +
  • +
  • +

    Supported object types: "default", "html", "markdown", "latex", "latex_tabular", "typst", "data.frame", "tinytable", "gt", "kableExtra", "huxtable", "flextable", "DT", "jupyter". The "modelsummary_list" value produces a lightweight object which can be saved and fed back to the modelsummary function.

    +
  • +
  • +

    The "default" output format can be set to "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown"

    +
      +
    • +

      If the user does not choose a default value, the packages listed above are tried in sequence.

      +
    • +
    • +

      Session-specific configuration: options(“modelsummary_factory_default” = “gt”)

      +
    • +
    • +

      Persistent configuration: config_modelsummary(output = “markdown”)

      +
    • +
    +
  • +
  • +

    Warning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.

    +
  • +
  • +

    LaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.

    +
  • +
+
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
+
+title + +string +
+notes + +list or vector of notes to append to the bottom of the table. +
+align + +

A string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.

+
    +
  • +

    "l": left-aligned column

    +
  • +
  • +

    "c": centered column

    +
  • +
  • +

    "r": right-aligned column

    +
  • +
  • +

    "d": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.

    +
  • +
+
+add_columns + +a data.frame (or tibble) with the same number of rows as your main table. +
+add_rows + +a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. +
+sparse_header + +TRUE or FALSE. TRUE eliminates column headers which have a unique label across all columns, except for the row immediately above the data. FALSE keeps all headers. The order in which terms are entered in the formula determines the order in which headers appear. For example, x~mean*z will print the mean-related header above the z-related header.’ +
+escape + +boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE) +
+ + +all other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes. +

Details

+

Visit the ‘modelsummary’ website for more usage examples: https://modelsummary.com

+

The ‘datasummary’ function is a thin wrapper around the ‘tabular’ function from the ‘tables’ package. More details about table-making formulas can be found in the ‘tables’ package documentation: ?tables::tabular

+

Hierarchical or "nested" column labels are only available for these output formats: tinytable, kableExtra, gt, html, rtf, and LaTeX. When saving tables to other formats, nested labels will be combined to a "flat" header.

+

Global Options

+

The behavior of modelsummary can be modified by setting global options. For example:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
+

The rest of this section describes each of the options above.

+

+Model labels: default column names +

+

These global option changes the style of the default column headers:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
  • +

    options(modelsummary_panel_labels = “roman”)

    +
  • +
+

The supported styles are: "model", "panel", "arabic", "letters", "roman", "(arabic)", "(letters)", "(roman)"

+

The panel-specific option is only used when shape=“rbind”

+

+Table-making packages +

+

modelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:

+

options(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)

+

+Table themes +

+

Change the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html

+
    +
  • +

    modelsummary_theme_gt

    +
  • +
  • +

    modelsummary_theme_kableExtra

    +
  • +
  • +

    modelsummary_theme_huxtable

    +
  • +
  • +

    modelsummary_theme_flextable

    +
  • +
  • +

    modelsummary_theme_dataframe

    +
  • +
+

+Model extraction functions +

+

modelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:

+

options(modelsummary_get = “easystats”)

+

options(modelsummary_get = “broom”)

+

options(modelsummary_get = “all”)

+

+Formatting numeric entries +

+

By default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:

+

options(modelsummary_format_numeric_latex = “plain”)

+

options(modelsummary_format_numeric_latex = “mathmode”)

+

A similar option can be used to display numerical entries using MathJax in HTML tables:

+

options(modelsummary_format_numeric_html = “mathjax”)

+

+LaTeX preamble +

+

When creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.

+

[3]{}

+

Examples

+
+
library(modelsummary)
+
+library(modelsummary)
+
+# The left-hand side of the formula describes rows, and the right-hand side
+# describes columns. This table uses the "mpg" variable as a row and the "mean"
+# function as a column:
+
+datasummary(mpg ~ mean, data = mtcars)
+
+ + + + + +tinytable_oengsxmsr0dg0fewop2v + +
+ + + + + + + + + +
mean
mpg20.09
+
+ + +
+
# This table uses the "mean" function as a row and the "mpg" variable as a column:
+
+datasummary(mean ~ mpg, data = mtcars)
+
+ + + + + +tinytable_qiah97bez6yp3tb1yjz8 + +
+ + + + + + + + + +
mpg
mean20.09
+
+ + +
+
# Display several variables or functions of the data using the "+"
+# concatenation operator. This table has 2 rows and 2 columns:
+
+datasummary(hp + mpg ~ mean + sd, data = mtcars)
+
+ + + + + +tinytable_0rwqzbz7y1fs1jwtt2f3 + +
+ + + + + + + + + + + + + + + + + + +
meansd
hp 146.6968.56
mpg20.09 6.03
+
+ + +
+
# Nest variables or statistics inside a "factor" variable using the "*" nesting
+# operator. This table shows the mean of "hp" and "mpg" for each value of
+# "cyl":
+
+mtcars$cyl <- as.factor(mtcars$cyl)
+datasummary(hp + mpg ~ cyl * mean, data = mtcars)
+
+ + + + + +tinytable_9n5p3qmb9xrfcjfwzs4t + +
+ + + + + + + + + + + + + + + + + + + + + +
468
hp 82.64122.29209.21
mpg26.6619.74 15.10
+
+ + +
+
# If you don't want to convert your original data
+# to factors, you can use the 'Factor()'
+# function inside 'datasummary' to obtain an identical result:
+
+datasummary(hp + mpg ~ Factor(cyl) * mean, data = mtcars)
+
+ + + + + +tinytable_a48qfecth0mdjgg881bq + +
+ + + + + + + + + + + + + + + + + + + + + +
468
hp 82.64122.29209.21
mpg26.6619.74 15.10
+
+ + +
+
# You can nest several variables or statistics inside a factor by using
+# parentheses. This table shows the mean and the standard deviation for each
+# subset of "cyl":
+
+datasummary(hp + mpg ~ cyl * (mean + sd), data = mtcars)
+
+ + + + + +tinytable_gqhdjyyk9ganywtrpbtp + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
468
meansdmeansdmeansd
hp 82.6420.93122.2924.26209.2150.98
mpg26.664.51 19.74 1.45 15.10 2.56
+
+ + +
+
# Summarize all numeric variables with 'All()'
+datasummary(All(mtcars) ~ mean + sd, data = mtcars)
+
+ + + + + +tinytable_yjilnuk7uhhyqu79aocv + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
meansd
mpg 20.09 6.03
disp230.72123.94
hp 146.6968.56
drat3.60 0.53
wt 3.22 0.98
qsec17.85 1.79
vs 0.44 0.50
am 0.41 0.50
gear3.69 0.74
carb2.81 1.62
+
+ + +
+
# Define custom summary statistics. Your custom function should accept a vector
+# of numeric values and return a single numeric or string value:
+
+minmax <- function(x) sprintf("[%.2f, %.2f]", min(x), max(x))
+mean_na <- function(x) mean(x, na.rm = TRUE)
+
+datasummary(hp + mpg ~ minmax + mean_na, data = mtcars)
+
+ + + + + +tinytable_dqe39s3tigd92mr9n0si + +
+ + + + + + + + + + + + + + + + + + +
minmaxmean_na
hp [52.00, 335.00]146.69
mpg[10.40, 33.90] 20.09
+
+ + +
+
# To handle missing values, you can pass arguments to your functions using
+# '*Arguments()'
+
+datasummary(hp + mpg ~ mean * Arguments(na.rm = TRUE), data = mtcars)
+
+ + + + + +tinytable_3ewcp3pjk8wpjut9smtg + +
+ + + + + + + + + + + + + + + +
mean
hp 146.69
mpg20.09
+
+ + +
+
# For convenience, 'modelsummary' supplies several convenience functions
+# with the argument `na.rm=TRUE` by default: Mean, Median, Min, Max, SD, Var,
+# P0, P25, P50, P75, P100, NUnique, Histogram
+
+#datasummary(hp + mpg ~ Mean + SD + Histogram, data = mtcars)
+
+# These functions also accept a 'fmt' argument which allows you to
+# round/format the results
+
+datasummary(hp + mpg ~ Mean * Arguments(fmt = "%.3f") + SD * Arguments(fmt = "%.1f"), data = mtcars)
+
+ + + + + +tinytable_9ezlm1ah64gh1d4i6oco + +
+ + + + + + + + + + + + + + + + + + +
MeanSD
hp 146.68868.6
mpg20.091 6.0
+
+ + +
+
# Save your tables to a variety of output formats:
+f <- hp + mpg ~ Mean + SD
+#datasummary(f, data = mtcars, output = 'table.html')
+#datasummary(f, data = mtcars, output = 'table.tex')
+#datasummary(f, data = mtcars, output = 'table.md')
+#datasummary(f, data = mtcars, output = 'table.docx')
+#datasummary(f, data = mtcars, output = 'table.pptx')
+#datasummary(f, data = mtcars, output = 'table.jpg')
+#datasummary(f, data = mtcars, output = 'table.png')
+
+# Display human-readable code
+#datasummary(f, data = mtcars, output = 'html')
+#datasummary(f, data = mtcars, output = 'markdown')
+#datasummary(f, data = mtcars, output = 'latex')
+
+# Return a table object to customize using a table-making package
+#datasummary(f, data = mtcars, output = 'tinytable')
+#datasummary(f, data = mtcars, output = 'gt')
+#datasummary(f, data = mtcars, output = 'kableExtra')
+#datasummary(f, data = mtcars, output = 'flextable')
+#datasummary(f, data = mtcars, output = 'huxtable')
+
+# add_rows
+new_rows <- data.frame(a = 1:2, b = 2:3, c = 4:5)
+attr(new_rows, 'position') <- c(1, 3)
+datasummary(mpg + hp ~ mean + sd, data = mtcars, add_rows = new_rows)
+
+ + + + + +tinytable_zpjqcle29gs9e5zczhfn + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
meansd
1.002.00 4.00
mpg 20.09 6.03
2.003.00 5.00
hp 146.6968.56
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/datasummary_balance.html b/docs/man/datasummary_balance.html new file mode 100644 index 000000000..101f43fbf --- /dev/null +++ b/docs/man/datasummary_balance.html @@ -0,0 +1,1412 @@ + + + + + + +modelsummary: Data and Model Summaries in R – datasummary_balance + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Balance table: Summary statistics for different subsets of the data (e.g., control and treatment groups)

+

Description

+

Creates balance tables with summary statistics for different subsets of the data (e.g., control and treatment groups). It can also be used to create summary tables for full data sets. See the Details and Examples sections below, and the vignettes on the modelsummary website:

+
    +
  • +

    https://modelsummary.com/

    +
  • +
  • +

    https://modelsummary.com/articles/datasummary.html

    +
  • +

Usage

+
datasummary_balance(
+  formula,
+  data,
+  output = "default",
+  fmt = fmt_decimal(digits = 1, pdigits = 3),
+  title = NULL,
+  notes = NULL,
+  align = NULL,
+  stars = FALSE,
+  add_columns = NULL,
+  add_rows = NULL,
+  dinm = TRUE,
+  dinm_statistic = "std.error",
+  escape = TRUE,
+  ...
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+formula + +
    +
  • +

    ~1: show summary statistics for the full dataset

    +
  • +
  • +

    one-sided formula: with the "condition" or "column" variable on the right-hand side.

    +
  • +
  • +

    two-side formula: with the subset of variables to summarize on the left-hand side and the condition variable on the right-hand side.

    +
  • +
+
+data + +A data.frame (or tibble). If this data includes columns called "blocks", "clusters", and/or "weights", the "estimatr" package will consider them when calculating the difference in means. If there is a weights column, the reported mean and standard errors will also be weighted. +
+output + +

filename or object type (character string)

+
    +
  • +

    Supported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg

    +
  • +
  • +

    Supported object types: "default", "html", "markdown", "latex", "latex_tabular", "typst", "data.frame", "tinytable", "gt", "kableExtra", "huxtable", "flextable", "DT", "jupyter". The "modelsummary_list" value produces a lightweight object which can be saved and fed back to the modelsummary function.

    +
  • +
  • +

    The "default" output format can be set to "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown"

    +
      +
    • +

      If the user does not choose a default value, the packages listed above are tried in sequence.

      +
    • +
    • +

      Session-specific configuration: options(“modelsummary_factory_default” = “gt”)

      +
    • +
    • +

      Persistent configuration: config_modelsummary(output = “markdown”)

      +
    • +
    +
  • +
  • +

    Warning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.

    +
  • +
  • +

    LaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.

    +
  • +
+
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
+
+title + +string +
+notes + +list or vector of notes to append to the bottom of the table. +
+align + +

A string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.

+
    +
  • +

    "l": left-aligned column

    +
  • +
  • +

    "c": centered column

    +
  • +
  • +

    "r": right-aligned column

    +
  • +
  • +

    "d": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.

    +
  • +
+
+stars + +

to indicate statistical significance

+
    +
  • +

    FALSE (default): no significance stars.

    +
  • +
  • +

    TRUE: +=.1, =.05, =.01, =0.001

    +
  • +
  • +

    Named numeric vector for custom stars such as c(’*’ = .1, ‘+’ = .05)

    +
  • +
  • +

    Note: a legend will not be inserted at the bottom of the table when the estimate or statistic arguments use "glue strings" with stars.

    +
  • +
+
+add_columns + +a data.frame (or tibble) with the same number of rows as your main table. +
+add_rows + +a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. +
+dinm + +TRUE calculates a difference in means with uncertainty estimates. This option is only available if the estimatr package is installed. If data includes columns named "blocks", "clusters", or "weights", this information will be taken into account automatically by estimatr::difference_in_means. +
+dinm_statistic + +string: "std.error" or "p.value" +
+escape + +boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE) +
+ + +all other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes. +

Global Options

+

The behavior of modelsummary can be modified by setting global options. For example:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
+

The rest of this section describes each of the options above.

+

+Model labels: default column names +

+

These global option changes the style of the default column headers:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
  • +

    options(modelsummary_panel_labels = “roman”)

    +
  • +
+

The supported styles are: "model", "panel", "arabic", "letters", "roman", "(arabic)", "(letters)", "(roman)"

+

The panel-specific option is only used when shape=“rbind”

+

+Table-making packages +

+

modelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:

+

options(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)

+

+Table themes +

+

Change the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html

+
    +
  • +

    modelsummary_theme_gt

    +
  • +
  • +

    modelsummary_theme_kableExtra

    +
  • +
  • +

    modelsummary_theme_huxtable

    +
  • +
  • +

    modelsummary_theme_flextable

    +
  • +
  • +

    modelsummary_theme_dataframe

    +
  • +
+

+Model extraction functions +

+

modelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:

+

options(modelsummary_get = “easystats”)

+

options(modelsummary_get = “broom”)

+

options(modelsummary_get = “all”)

+

+Formatting numeric entries +

+

By default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:

+

options(modelsummary_format_numeric_latex = “plain”)

+

options(modelsummary_format_numeric_latex = “mathmode”)

+

A similar option can be used to display numerical entries using MathJax in HTML tables:

+

options(modelsummary_format_numeric_html = “mathjax”)

+

+LaTeX preamble +

+

When creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.

+

[3]{}

+

Examples

+
+ +
+ + + + + +tinytable_axqoysufa43bdk80q4fq + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
01
MeanStd. Dev.MeanStd. Dev.Diff. in MeansStd. Error
mpg 17.1 3.8 24.4 6.2 7.2 1.9
cyl 6.9 1.5 5.1 1.6 -1.9 0.6
disp290.4110.2143.587.2-146.835.0
hp 160.353.9 126.884.1-33.4 26.4
drat3.3 0.4 4.0 0.4 0.8 0.1
wt 3.8 0.8 2.4 0.6 -1.4 0.2
qsec18.2 1.8 17.4 1.8 -0.8 0.6
vs 0.4 0.5 0.5 0.5 0.2 0.2
gear3.2 0.4 4.4 0.5 1.2 0.2
carb2.7 1.1 2.9 2.2 0.2 0.7
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/datasummary_correlation.html b/docs/man/datasummary_correlation.html new file mode 100644 index 000000000..6d662811c --- /dev/null +++ b/docs/man/datasummary_correlation.html @@ -0,0 +1,1878 @@ + + + + + + +modelsummary: Data and Model Summaries in R – datasummary_correlation + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Generate a correlation table for all numeric variables in your dataset.

+

Description

+

The names of the variables displayed in the correlation table are the names of the columns in the data. You can rename those columns (with or without spaces) to produce a table of human-readable variables. See the Details and Examples sections below, and the vignettes on the modelsummary website:

+
    +
  • +

    https://modelsummary.com/

    +
  • +
  • +

    https://modelsummary.com/articles/datasummary.html

    +
  • +

Usage

+
datasummary_correlation(
+  data,
+  output = "default",
+  method = "pearson",
+  fmt = 2,
+  align = NULL,
+  add_rows = NULL,
+  add_columns = NULL,
+  title = NULL,
+  notes = NULL,
+  escape = TRUE,
+  ...
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+data + +A data.frame (or tibble) +
+output + +

filename or object type (character string)

+
    +
  • +

    Supported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg

    +
  • +
  • +

    Supported object types: "default", "html", "markdown", "latex", "latex_tabular", "typst", "data.frame", "tinytable", "gt", "kableExtra", "huxtable", "flextable", "DT", "jupyter". The "modelsummary_list" value produces a lightweight object which can be saved and fed back to the modelsummary function.

    +
  • +
  • +

    The "default" output format can be set to "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown"

    +
      +
    • +

      If the user does not choose a default value, the packages listed above are tried in sequence.

      +
    • +
    • +

      Session-specific configuration: options(“modelsummary_factory_default” = “gt”)

      +
    • +
    • +

      Persistent configuration: config_modelsummary(output = “markdown”)

      +
    • +
    +
  • +
  • +

    Warning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.

    +
  • +
  • +

    LaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.

    +
  • +
+
+method + +

character or function

+
    +
  • +

    character: "pearson", "kendall", "spearman", or "pearspear" (Pearson correlations above and Spearman correlations below the diagonal)

    +
  • +
  • +

    function: takes a data.frame with numeric columns and returns a square matrix or data.frame with unique row.names and colnames corresponding to variable names. Note that the datasummary_correlation_format can often be useful for formatting the output of custom correlation functions.

    +
  • +
+
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
+
+align + +

A string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.

+
    +
  • +

    "l": left-aligned column

    +
  • +
  • +

    "c": centered column

    +
  • +
  • +

    "r": right-aligned column

    +
  • +
  • +

    "d": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.

    +
  • +
+
+add_rows + +a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. +
+add_columns + +a data.frame (or tibble) with the same number of rows as your main table. +
+title + +string +
+notes + +list or vector of notes to append to the bottom of the table. +
+escape + +boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE) +
+ + +other parameters are passed through to the table-making packages. +

Global Options

+

The behavior of modelsummary can be modified by setting global options. For example:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
+

The rest of this section describes each of the options above.

+

+Model labels: default column names +

+

These global option changes the style of the default column headers:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
  • +

    options(modelsummary_panel_labels = “roman”)

    +
  • +
+

The supported styles are: "model", "panel", "arabic", "letters", "roman", "(arabic)", "(letters)", "(roman)"

+

The panel-specific option is only used when shape=“rbind”

+

+Table-making packages +

+

modelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:

+

options(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)

+

+Table themes +

+

Change the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html

+
    +
  • +

    modelsummary_theme_gt

    +
  • +
  • +

    modelsummary_theme_kableExtra

    +
  • +
  • +

    modelsummary_theme_huxtable

    +
  • +
  • +

    modelsummary_theme_flextable

    +
  • +
  • +

    modelsummary_theme_dataframe

    +
  • +
+

+Model extraction functions +

+

modelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:

+

options(modelsummary_get = “easystats”)

+

options(modelsummary_get = “broom”)

+

options(modelsummary_get = “all”)

+

+Formatting numeric entries +

+

By default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:

+

options(modelsummary_format_numeric_latex = “plain”)

+

options(modelsummary_format_numeric_latex = “mathmode”)

+

A similar option can be used to display numerical entries using MathJax in HTML tables:

+

options(modelsummary_format_numeric_html = “mathjax”)

+

+LaTeX preamble +

+

When creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.

+

[3]{}

+

Examples

+
+
library(modelsummary)
+
+library(modelsummary)
+
+# clean variable names (base R)
+dat <- mtcars[, c("mpg", "hp")]
+colnames(dat) <- c("Miles / Gallon", "Horse Power")
+datasummary_correlation(dat)
+
+ + + + + +tinytable_lqm5yep0ilher18ulbvk + +
+ + + + + + + + + + + + + + + + + + +
Miles / GallonHorse Power
Miles / Gallon1 .
Horse Power -.781
+
+ + +
+
# clean variable names (tidyverse)
+library(tidyverse)
+dat <- mtcars %>%
+  select(`Miles / Gallon` = mpg,
+         `Horse Power` = hp)
+datasummary_correlation(dat)
+
+ + + + + +tinytable_3kclndgxea7xtjuujcpi + +
+ + + + + + + + + + + + + + + + + + +
Miles / GallonHorse Power
Miles / Gallon1 .
Horse Power -.781
+
+ + +
+
# alternative methods
+datasummary_correlation(dat, method = "pearspear")
+
+ + + + + +tinytable_dz0p5x5la5zv0nyf1slh + +
+ + + + + + + + + + + + + + + + + + +
Miles / GallonHorse Power
Miles / Gallon1 -.78
Horse Power -.891
+
+ + +
+
# custom function
+cor_fun <- function(x) cor(x, method = "kendall")
+datasummary_correlation(dat, method = cor_fun)
+
+ + + + + +tinytable_smtzy6r4mpzoxb0ao498 + +
+ + + + + + + + + + + + + + + + + + +
Miles / GallonHorse Power
Miles / Gallon1.00-.74
Horse Power -.741.00
+
+ + +
+
# rename columns alphabetically and include a footnote for reference
+note <- sprintf("(%s) %s", letters[1:ncol(dat)], colnames(dat))
+note <- paste(note, collapse = "; ")
+
+colnames(dat) <- sprintf("(%s)", letters[1:ncol(dat)])
+
+datasummary_correlation(dat, notes = note)
+
+ + + + + +tinytable_j2w1c0tbx9jr58f7almw + +
+ + + + + + + + + + + + + + + + + + + +
(a)(b)
(a) Miles / Gallon; (b) Horse Power
(a)1 .
(b)-.781
+
+ + +
+
# `datasummary_correlation_format`: custom function with formatting
+dat <- mtcars[, c("mpg", "hp", "disp")]
+
+cor_fun <- function(x) {
+  out <- cor(x, method = "kendall")
+  datasummary_correlation_format(
+    out,
+    fmt = 2,
+    upper_triangle = "x",
+    diagonal = ".")
+}
+
+datasummary_correlation(dat, method = cor_fun)
+
+ + + + + +tinytable_qm5ndlgshzupo12elph5 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
mpghpdisp
mpg . x x
hp -.74. x
disp-.77.67.
+
+ + +
+
# use kableExtra and psych to color significant cells
+library(psych)
+library(kableExtra)
+
+dat <- mtcars[, c("vs", "hp", "gear")]
+
+cor_fun <- function(dat) {
+  # compute correlations and format them
+  correlations <- data.frame(cor(dat))
+  correlations <- datasummary_correlation_format(correlations, fmt = 2)
+
+  # calculate pvalues using the `psych` package
+  pvalues <- psych::corr.test(dat)$p
+
+  # use `kableExtra::cell_spec` to color significant cells
+  for (i in 1:nrow(correlations)) {
+    for (j in 1:ncol(correlations)) {
+      if (pvalues[i, j] < 0.05 && i != j) {
+        correlations[i, j] <- cell_spec(correlations[i, j], background = "pink")
+      }
+    }
+  }
+  return(correlations)
+}
+
+# The `escape=FALSE` is important here!
+datasummary_correlation(dat, method = cor_fun, escape = FALSE)
+
+ + + + + +tinytable_72vj0rbb0ntxzq78x1ey + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
vshpgear
vs 1.00 -.72.21
hp -.721.00 -.13
gear.21 -.13 1.00
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/datasummary_correlation_format.html b/docs/man/datasummary_correlation_format.html new file mode 100644 index 000000000..ce66cd2cf --- /dev/null +++ b/docs/man/datasummary_correlation_format.html @@ -0,0 +1,1029 @@ + + + + + + +modelsummary: Data and Model Summaries in R – datasummary_correlation_format + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Format the content of a correlation table

+

Description

+

Mostly for internal use, but can be useful when users supply a function to the method argument of datasummary_correlation.

+

Usage

+
datasummary_correlation_format(
+  x,
+  fmt,
+  leading_zero = FALSE,
+  diagonal = NULL,
+  upper_triangle = NULL
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + +
+x + +square numeric matrix +
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
+
+leading_zero + +boolean. If FALSE, leading zeros are removed +
+diagonal + +character or NULL. If character, all elements of the diagonal are replaced by the same character (e.g., "1"). +
+upper_triangle + +character or NULL. If character, all elements of the upper triangle are replaced by the same character (e.g., "" or "."). +

Examples

+
+
library(modelsummary)
+
+library(modelsummary)
+
+dat <- mtcars[, c("mpg", "hp", "disp")]
+
+cor_fun <- function(x) {
+  out <- cor(x, method = "kendall")
+  datasummary_correlation_format(
+    out,
+    fmt = 2,
+    upper_triangle = "x",
+    diagonal = ".")
+}
+
+datasummary_correlation(dat, method = cor_fun)
+
+ + + + + +tinytable_jyfmr10er0pi83lzoint + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
mpghpdisp
mpg . x x
hp -.74. x
disp-.77.67.
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/datasummary_crosstab.html b/docs/man/datasummary_crosstab.html new file mode 100644 index 000000000..37309aaad --- /dev/null +++ b/docs/man/datasummary_crosstab.html @@ -0,0 +1,1880 @@ + + + + + + +modelsummary: Data and Model Summaries in R – datasummary_crosstab + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Cross tabulations for categorical variables

+

Description

+

Convenience function to tabulate counts, cell percentages, and row/column percentages for categorical variables. See the Details section for a description of the internal design. For more complex cross tabulations, use datasummary directly. See the Details and Examples sections below, and the vignettes on the modelsummary website:

+
    +
  • +

    https://modelsummary.com/

    +
  • +
  • +

    https://modelsummary.com/articles/datasummary.html

    +
  • +

Usage

+
datasummary_crosstab(
+  formula,
+  statistic = 1 ~ 1 + N + Percent("row"),
+  data,
+  output = "default",
+  fmt = 1,
+  title = NULL,
+  notes = NULL,
+  align = NULL,
+  add_columns = NULL,
+  add_rows = NULL,
+  sparse_header = TRUE,
+  escape = TRUE,
+  ...
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+formula + +A two-sided formula to describe the table: rows ~ columns, where rows and columns are variables in the data. Rows and columns may contain interactions, e.g., var1 * var2 ~ var3. +
+statistic + +A formula of the form 1 ~ 1 + N + Percent(“row”). The left-hand side may only be empty or contain a 1 to include row totals. The right-hand side may contain: 1 for column totals, N for counts, Percent() for cell percentages, Percent(“row”) for row percentages, Percent(“col”) for column percentages. +
+data + +A data.frame (or tibble) +
+output + +

filename or object type (character string)

+
    +
  • +

    Supported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg

    +
  • +
  • +

    Supported object types: "default", "html", "markdown", "latex", "latex_tabular", "typst", "data.frame", "tinytable", "gt", "kableExtra", "huxtable", "flextable", "DT", "jupyter". The "modelsummary_list" value produces a lightweight object which can be saved and fed back to the modelsummary function.

    +
  • +
  • +

    The "default" output format can be set to "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown"

    +
      +
    • +

      If the user does not choose a default value, the packages listed above are tried in sequence.

      +
    • +
    • +

      Session-specific configuration: options(“modelsummary_factory_default” = “gt”)

      +
    • +
    • +

      Persistent configuration: config_modelsummary(output = “markdown”)

      +
    • +
    +
  • +
  • +

    Warning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.

    +
  • +
  • +

    LaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.

    +
  • +
+
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
+
+title + +string +
+notes + +list or vector of notes to append to the bottom of the table. +
+align + +

A string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.

+
    +
  • +

    "l": left-aligned column

    +
  • +
  • +

    "c": centered column

    +
  • +
  • +

    "r": right-aligned column

    +
  • +
  • +

    "d": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.

    +
  • +
+
+add_columns + +a data.frame (or tibble) with the same number of rows as your main table. +
+add_rows + +a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. +
+sparse_header + +TRUE or FALSE. TRUE eliminates column headers which have a unique label across all columns, except for the row immediately above the data. FALSE keeps all headers. The order in which terms are entered in the formula determines the order in which headers appear. For example, x~mean*z will print the mean-related header above the z-related header.’ +
+escape + +boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE) +
+ + +all other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes. +

Details

+

datasummary_crosstab is a wrapper around the datasummary function. This wrapper works by creating a customized formula and by feeding it to datasummary. The customized formula comes in two parts.

+

First, we take a two-sided formula supplied by the formula argument. All variables of that formula are wrapped in a Factor() call to ensure that the variables are treated as categorical.

+

Second, the statistic argument gives a two-sided formula which specifies the statistics to include in the table. datasummary_crosstab modifies this formula automatically to include "clean" labels.

+

Finally, the formula and statistic formulas are combined into a single formula which is fed directly to the datasummary function to produce the table.

+

Variables in formula are automatically wrapped in Factor().

+

Global Options

+

The behavior of modelsummary can be modified by setting global options. For example:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
+

The rest of this section describes each of the options above.

+

+Model labels: default column names +

+

These global option changes the style of the default column headers:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
  • +

    options(modelsummary_panel_labels = “roman”)

    +
  • +
+

The supported styles are: "model", "panel", "arabic", "letters", "roman", "(arabic)", "(letters)", "(roman)"

+

The panel-specific option is only used when shape=“rbind”

+

+Table-making packages +

+

modelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:

+

options(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)

+

+Table themes +

+

Change the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html

+
    +
  • +

    modelsummary_theme_gt

    +
  • +
  • +

    modelsummary_theme_kableExtra

    +
  • +
  • +

    modelsummary_theme_huxtable

    +
  • +
  • +

    modelsummary_theme_flextable

    +
  • +
  • +

    modelsummary_theme_dataframe

    +
  • +
+

+Model extraction functions +

+

modelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:

+

options(modelsummary_get = “easystats”)

+

options(modelsummary_get = “broom”)

+

options(modelsummary_get = “all”)

+

+Formatting numeric entries +

+

By default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:

+

options(modelsummary_format_numeric_latex = “plain”)

+

options(modelsummary_format_numeric_latex = “mathmode”)

+

A similar option can be used to display numerical entries using MathJax in HTML tables:

+

options(modelsummary_format_numeric_html = “mathjax”)

+

+LaTeX preamble +

+

When creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.

+

[3]{}

+

Examples

+
+
library(modelsummary)
+
+library(modelsummary)
+
+# crosstab of two variables, showing counts, row percentages, and row/column totals
+datasummary_crosstab(cyl ~ gear, data = mtcars)
+
+ + + + + +tinytable_53soqsg0zyxpdd7d792m + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cyl 345All
4 N 1 8 2 11
% row9.1 72.718.2100.0
6 N 2 4 1 7
% row28.657.114.3100.0
8 N 12 0 2 14
% row85.70.0 14.3100.0
AllN 15 12 5 32
% row46.937.515.6100.0
+
+ + +
+
# crosstab of two variables, showing counts only and no totals
+datasummary_crosstab(cyl ~ gear, statistic = ~ N, data = mtcars)
+
+ + + + + +tinytable_woqc6c15y86ppbroec7i + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cyl 345
4N1 82
6N2 41
8N1202
+
+ + +
+
# crosstab of three variables
+  datasummary_crosstab(am * cyl ~ gear, data = mtcars)
+
+ + + + + +tinytable_nueq2d2yzkxgab84fm9s + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
amcyl 345All
04 N 1 2 0 3
% row33.3 66.70.0 100.0
6 N 2 2 0 4
% row50.0 50.00.0 100.0
8 N 12 0 0 12
% row100.00.0 0.0 100.0
14 N 0 6 2 8
% row0.0 75.025.0 100.0
6 N 0 2 1 3
% row0.0 66.733.3 100.0
8 N 0 0 2 2
% row0.0 0.0 100.0100.0
AllN 15 12 5 32
% row46.9 37.515.6 100.0
+
+ + +
+
# crosstab with two variables and column percentages 
+datasummary_crosstab(am ~ gear, statistic = ~ Percent("col"), data = mtcars)
+
+ + + + + +tinytable_v0t9xr1poxhq1onhr8cf + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
am 345
0% col100.033.30.0
1% col0.0 66.7100.0
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/datasummary_df.html b/docs/man/datasummary_df.html new file mode 100644 index 000000000..cd12bc80c --- /dev/null +++ b/docs/man/datasummary_df.html @@ -0,0 +1,980 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – datasummary_df + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Draw a table from a data.frame

+
+

Description

+

Draw a table from a data.frame

+
+
+

Usage

+
datasummary_df(
+  data,
+  output = "default",
+  fmt = 2,
+  align = NULL,
+  hrule = NULL,
+  title = NULL,
+  notes = NULL,
+  add_rows = NULL,
+  add_columns = NULL,
+  escape = TRUE,
+  ...
+)
+
+
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+data + +A data.frame (or tibble) +
+output + +

filename or object type (character string)

+
    +
  • +

    Supported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg

    +
  • +
  • +

    Supported object types: "default", "html", "markdown", "latex", "latex_tabular", "typst", "data.frame", "tinytable", "gt", "kableExtra", "huxtable", "flextable", "DT", "jupyter". The "modelsummary_list" value produces a lightweight object which can be saved and fed back to the modelsummary function.

    +
  • +
  • +

    The "default" output format can be set to "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown"

    +
      +
    • +

      If the user does not choose a default value, the packages listed above are tried in sequence.

      +
    • +
    • +

      Session-specific configuration: options(“modelsummary_factory_default” = “gt”)

      +
    • +
    • +

      Persistent configuration: config_modelsummary(output = “markdown”)

      +
    • +
    +
  • +
  • +

    Warning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.

    +
  • +
  • +

    LaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.

    +
  • +
+
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
+
+align + +

A string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.

+
    +
  • +

    "l": left-aligned column

    +
  • +
  • +

    "c": centered column

    +
  • +
  • +

    "r": right-aligned column

    +
  • +
  • +

    "d": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.

    +
  • +
+
+hrule + +position of horizontal rules (integer vector) +
+title + +string +
+notes + +list or vector of notes to append to the bottom of the table. +
+add_rows + +a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. +
+add_columns + +a data.frame (or tibble) with the same number of rows as your main table. +
+escape + +boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE) +
+ + +all other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes. +
+
+
+

References

+

Arel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’

+ + +
+
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/man/datasummary_skim.html b/docs/man/datasummary_skim.html new file mode 100644 index 000000000..ccde7c80e --- /dev/null +++ b/docs/man/datasummary_skim.html @@ -0,0 +1,1079 @@ + + + + + + +modelsummary: Data and Model Summaries in R – datasummary_skim + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Quick overview of numeric or categorical variables

+

Description

+

This function was inspired by the excellent skimr package for R. See the Details and Examples sections below, and the vignettes on the modelsummary website:

+
    +
  • +

    https://modelsummary.com/

    +
  • +
  • +

    https://modelsummary.com/articles/datasummary.html

    +
  • +

Usage

+
datasummary_skim(
+  data,
+  output = "default",
+  type = "all",
+  fmt = 1,
+  title = NULL,
+  notes = NULL,
+  align = NULL,
+  escape = TRUE,
+  by = NULL,
+  fun_numeric = list(Unique = NUnique, `Missing Pct.` = PercentMissing, Mean = Mean, SD =
+    SD, Min = Min, Median = Median, Max = Max, Histogram = function(x) ""),
+  ...
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+data + +A data.frame (or tibble) +
+output + +

filename or object type (character string)

+
    +
  • +

    Supported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg

    +
  • +
  • +

    Supported object types: "default", "html", "markdown", "latex", "latex_tabular", "typst", "data.frame", "tinytable", "gt", "kableExtra", "huxtable", "flextable", "DT", "jupyter". The "modelsummary_list" value produces a lightweight object which can be saved and fed back to the modelsummary function.

    +
  • +
  • +

    The "default" output format can be set to "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown"

    +
      +
    • +

      If the user does not choose a default value, the packages listed above are tried in sequence.

      +
    • +
    • +

      Session-specific configuration: options(“modelsummary_factory_default” = “gt”)

      +
    • +
    • +

      Persistent configuration: config_modelsummary(output = “markdown”)

      +
    • +
    +
  • +
  • +

    Warning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.

    +
  • +
  • +

    LaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.

    +
  • +
+
+type + +String. Variables to summarize: "all", "numeric", "categorical", "dataset" +
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
+
+title + +string +
+notes + +list or vector of notes to append to the bottom of the table. +
+align + +

A string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.

+
    +
  • +

    "l": left-aligned column

    +
  • +
  • +

    "c": centered column

    +
  • +
  • +

    "r": right-aligned column

    +
  • +
  • +

    "d": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.

    +
  • +
+
+escape + +boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE) +
+by + +Character vector of grouping variables to compute statistics over. +
+fun_numeric + +Named list of funtions to apply to each column of data. If fun_numeric includes "Histogram" or "Density", inline plots are inserted. +
+ + +all other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes. +

Global Options

+

The behavior of modelsummary can be modified by setting global options. For example:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
+

The rest of this section describes each of the options above.

+

+Model labels: default column names +

+

These global option changes the style of the default column headers:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
  • +

    options(modelsummary_panel_labels = “roman”)

    +
  • +
+

The supported styles are: "model", "panel", "arabic", "letters", "roman", "(arabic)", "(letters)", "(roman)"

+

The panel-specific option is only used when shape=“rbind”

+

+Table-making packages +

+

modelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:

+

options(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)

+

+Table themes +

+

Change the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html

+
    +
  • +

    modelsummary_theme_gt

    +
  • +
  • +

    modelsummary_theme_kableExtra

    +
  • +
  • +

    modelsummary_theme_huxtable

    +
  • +
  • +

    modelsummary_theme_flextable

    +
  • +
  • +

    modelsummary_theme_dataframe

    +
  • +
+

+Model extraction functions +

+

modelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:

+

options(modelsummary_get = “easystats”)

+

options(modelsummary_get = “broom”)

+

options(modelsummary_get = “all”)

+

+Formatting numeric entries +

+

By default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:

+

options(modelsummary_format_numeric_latex = “plain”)

+

options(modelsummary_format_numeric_latex = “mathmode”)

+

A similar option can be used to display numerical entries using MathJax in HTML tables:

+

options(modelsummary_format_numeric_html = “mathjax”)

+

+LaTeX preamble +

+

When creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.

+

[3]{}

+

References

+

Arel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’

+

Examples

+
+
library(modelsummary)
+
+
+dat <- mtcars
+dat$vs <- as.logical(dat$vs)
+dat$cyl <- as.factor(dat$cyl)
+datasummary_skim(dat)
+datasummary_skim(dat, type = "categorical")
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/dvnames.html b/docs/man/dvnames.html new file mode 100644 index 000000000..e1dcbf8c7 --- /dev/null +++ b/docs/man/dvnames.html @@ -0,0 +1,1264 @@ + + + + + + +modelsummary: Data and Model Summaries in R – dvnames + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Title models with their dependent variables

+

Description

+

A convenience function for use with a regression model or list of regression models. Returns a named list of models, where the names are the models’ respective dependent variables. Pass your list of models to dvnames before sending to modelsummary to automatically get dependent variable-titled columns.

+

Usage

+
dvnames(models, number = FALSE, strip = FALSE, fill = "Model")
+
+

Arguments

+ + + + + + + + + + + + + + + + + +
+models + +A regression model or list of regression models +
+number + +Should the models be numbered (1), (2), etc., in addition to their dependent variable names? +
+strip + +boolean FALSE returns the dependent variable names as they appear in the model. TRUE returns the dependent variable names as they appear in the data, without transformations. +
+fill + +If insight::find_response() cannot find a response, the column title to use in its place. Set to ’ ’ to leave blank. +

Examples

+
+
library(modelsummary)
+
+
+m1 <- lm(mpg ~ hp, data = mtcars)
+m2 <- lm(mpg ~ hp + wt, data = mtcars)
+
+# Without dvnames, column names are (1) and (2)
+modelsummary(list(m1, m2))
+
+ + + + + +tinytable_ur5sjdxkkai5miru692t + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)30.099 37.227
(1.634)(1.599)
hp -0.068 -0.032
(0.010)(0.009)
wt -3.878
(0.633)
Num.Obs. 32 32
R2 0.602 0.827
R2 Adj. 0.589 0.815
AIC 181.2 156.7
BIC 185.6 162.5
Log.Lik. -87.619-74.326
F 45.460 69.211
RMSE 3.74 2.47
+
+ + +
+
# With dvnames, they are "mpg" and "mpg"
+modelsummary(dvnames(list(m1,m2)))
+
+ + + + + +tinytable_koq29n1et1odeaehv0mo + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mpgmpg
(Intercept)30.099 37.227
(1.634)(1.599)
hp -0.068 -0.032
(0.010)(0.009)
wt -3.878
(0.633)
Num.Obs. 32 32
R2 0.602 0.827
R2 Adj. 0.589 0.815
AIC 181.2 156.7
BIC 185.6 162.5
Log.Lik. -87.619-74.326
F 45.460 69.211
RMSE 3.74 2.47
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/figures/modelsummary_gallery.gif b/docs/man/figures/modelsummary_gallery.gif new file mode 100644 index 000000000..0588247da Binary files /dev/null and b/docs/man/figures/modelsummary_gallery.gif differ diff --git a/docs/man/figures/squirrel.png b/docs/man/figures/squirrel.png new file mode 100644 index 000000000..257b598e6 Binary files /dev/null and b/docs/man/figures/squirrel.png differ diff --git a/docs/man/fmt_decimal.html b/docs/man/fmt_decimal.html new file mode 100644 index 000000000..01bf2f802 --- /dev/null +++ b/docs/man/fmt_decimal.html @@ -0,0 +1,844 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – fmt_decimal + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Rounding with decimal digits in the fmt argument

+
+

Description

+

Rounding with decimal digits in the fmt argument

+
+
+

Usage

+
fmt_decimal(digits = 3, pdigits = NULL, ...)
+
+
+
+

Arguments

+ + + + + + + + + + + + + +
+digits + +Number of decimal digits to keep, including trailing zeros. +
+pdigits + +Number of decimal digits to keep for p values. If NULL, the value of digits is used. +
+ + +Additional arguments are passed to the format() function (e.g., big.marks, scientific). See ?format +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/fmt_sci.html b/docs/man/fmt_sci.html new file mode 100644 index 000000000..e154d3e16 --- /dev/null +++ b/docs/man/fmt_sci.html @@ -0,0 +1,836 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – fmt_sci + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Rounding using scientific notation

+
+

Description

+

Rounding using scientific notation

+
+
+

Usage

+
fmt_sci(digits = 3, ...)
+
+
+
+

Arguments

+ + + + + + + + + +
+digits + +a positive integer indicating how many significant digits are to be used for numeric and complex x. +
+ + +additional arguments passed to format(). +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/fmt_significant.html b/docs/man/fmt_significant.html new file mode 100644 index 000000000..4acb21600 --- /dev/null +++ b/docs/man/fmt_significant.html @@ -0,0 +1,836 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – fmt_significant + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Rounding with significant digits in the fmt argument

+
+

Description

+

The number of decimal digits to keep after the decimal is assessed

+
+
+

Usage

+
fmt_significant(digits = 3, ...)
+
+
+
+

Arguments

+ + + + + + + + + +
+digits + +Number of significant digits to keep. +
+ + +Additional arguments are passed to the format() function (e.g., big.marks, scientific). See ?format +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/fmt_sprintf.html b/docs/man/fmt_sprintf.html new file mode 100644 index 000000000..4dfe73d92 --- /dev/null +++ b/docs/man/fmt_sprintf.html @@ -0,0 +1,828 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – fmt_sprintf + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Rounding with the sprintf() function in the fmt argument

+
+

Description

+

Rounding with the sprintf() function in the fmt argument

+
+
+

Usage

+
fmt_sprintf(fmt)
+
+
+
+

Arguments

+ + + + + +
+fmt + +A string to control sprintf(), such as “%.3f” to keep 3 decimal digits. See ?sprintf +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/fmt_statistic.html b/docs/man/fmt_statistic.html new file mode 100644 index 000000000..da2e17f04 --- /dev/null +++ b/docs/man/fmt_statistic.html @@ -0,0 +1,836 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – fmt_statistic + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Rounding with decimal digits on a per-statistic basis in the fmt argument for modelsummary()

+
+

Description

+

Rounding with decimal digits on a per-statistic basis in the fmt argument for modelsummary()

+
+
+

Usage

+
fmt_statistic(..., default = 3)
+
+
+
+

Arguments

+ + + + + + + + + +
+ + +Statistic names and fmt value +
+default + +Number of decimal digits to keep for unspecified terms +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/fmt_term.html b/docs/man/fmt_term.html new file mode 100644 index 000000000..b6771f39f --- /dev/null +++ b/docs/man/fmt_term.html @@ -0,0 +1,836 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – fmt_term + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Rounding with decimal digits on a per-term basis in the fmt argument for modelsummary()

+
+

Description

+

Rounding with decimal digits on a per-term basis in the fmt argument for modelsummary()

+
+
+

Usage

+
fmt_term(..., default = 3)
+
+
+
+

Arguments

+ + + + + + + + + +
+ + +Term names and fmt value +
+default + +Number of decimal digits to keep for unspecified terms +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/get_estimates.html b/docs/man/get_estimates.html new file mode 100644 index 000000000..3ace4e279 --- /dev/null +++ b/docs/man/get_estimates.html @@ -0,0 +1,991 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – get_estimates + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Extract model estimates in a tidy format.

+
+

Description

+

A unified approach to extract results from a wide variety of models. For some models get_estimates attaches useful attributes to the output. You can access this information by calling the attributes function: attributes(get_estimates(model))

+
+
+

Usage

+
get_estimates(
+  model,
+  conf_level = 0.95,
+  vcov = NULL,
+  shape = NULL,
+  coef_rename = FALSE,
+  ...
+)
+
+
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+model + +a single model object +
+conf_level + +numeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models. +
+vcov + +

robust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):

+
    +
  • +

    NULL returns the default uncertainty estimates of the model object

    +
  • +
  • +

    string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (), but it is safer to define your own custom functions as described in the next bullet.

    +
  • +
  • +

    function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).

    +
  • +
  • +

    formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).

    +
  • +
  • +

    named list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.

    +
  • +
  • +

    a named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.

    +
  • +
+
+shape + +

NULL, formula, or string which determines the shape of a table.

+
    +
  • +

    NULL: Default shape with terms in rows and models in columns.

    +
  • +
  • +

    Formula: The left side determines what appears on rows, and the right side determines what appears on columns. The formula can include one or more group identifier(s) to display related terms together, which can be useful for models with multivariate outcomes or grouped coefficients (See examples section below). The group identifier(s) must be column names produced by: get_estimates(model). The group identifier(s) can be combined with the term identifier in a single column by using the colon to represent an interaction. If an incomplete formula is supplied (e.g., ~statistic), modelsummary tries to complete it automatically. Goodness-of-fit statistics are only appended to the bottom of the table when model is on the right hand side of the formula (i.e., columns). Potential shape values include:

    +
      +
    • +

      term + statistic ~ model: default

      +
    • +
    • +

      term ~ model + statistic: statistics in separate columns

      +
    • +
    • +

      model + statistic ~ term: models in rows and terms in columns

      +
    • +
    • +

      term + response + statistic ~ model: term and group id in separate columns

      +
    • +
    • +

      term : response + statistic ~ model: term and group id in a single column

      +
    • +
    • +

      term ~ response

      +
    • +
    +
  • +
  • +

    String: "cbind", "rbind", "rcollapse"

    +
      +
    • +

      "cbind": side-by-side models with autmoatic spanning column headers to group models (tinytable only feature).

      +
    • +
    • +

      "rbind" or "rcollapse": "panels" or "stacks" of regression models.

      +
    • +
    • +

      the models argument must be a (potentially named) nested list of models.

      +
    • +
    +
      +
    • +

      Unnamed nested list with 2 panels: list(list(model1, model2), list(model3, model4))

      +
    • +
    • +

      Named nested list with 2 panels: list(“Panel A” = list(model1, model2), “Panel B” = list(model3, model4))

      +
    • +
    • +

      Named panels and named models: list(“Panel A” = list(“(I)” = model1, “(II)” = model2), “Panel B” = list(“(I)” = model3, “(II)” = model4))

      +
    • +
    +
      +
    • +

      "rbind": Bind the rows of independent regression tables

      +
    • +
    • +

      "rcollapse": Bind the rows of regression tables and create a panel at the bottom where we "collapse" goodness-of-fit statistics which are identical across models.

      +
    • +
    +
  • +
+
+coef_rename + +

logical, named or unnamed character vector, or function

+
    +
  • +

    Logical: TRUE renames variables based on the "label" attribute of each column. See the Example section below.

    +
  • +
  • +

    Unnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.

    +
  • +
  • +

    Named character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c("hp:mpg"="hp X mpg")

    +
  • +
  • +

    Function: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)

    +
  • +
+
+ + +

all other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.

+
    +
  • +

    parameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:

    +
      +
    • +

      standardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.

      +
    • +
    +
  • +
  • +

    performance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:

    +
      +
    • +

      metrics, estimator, etc.

      +
    • +
    +
  • +
  • +

    tinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.

    +
  • +
+
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/get_gof.html b/docs/man/get_gof.html new file mode 100644 index 000000000..5834420c9 --- /dev/null +++ b/docs/man/get_gof.html @@ -0,0 +1,873 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – get_gof + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Extract goodness-of-fit statistics a tidy format.

+
+

Description

+

A unified approach to extract results from a wide variety of models. For some models get_gof attaches useful attributes to the output. You can access this information by calling the attributes function: attributes(get_estimates(model))

+
+
+

Usage

+
get_gof(model, gof_function = NULL, vcov_type = NULL, ...)
+
+
+
+

Arguments

+ + + + + + + + + + + + + + + + + +
+model + +a single model object +
+gof_function + +function which accepts a model object in the model argument and returns a 1-row data.frame with one custom goodness-of-fit statistic per column. +
+vcov_type + +string vcov type to add at the bottom of the table +
+ + +

all other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.

+
    +
  • +

    parameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:

    +
      +
    • +

      standardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.

      +
    • +
    +
  • +
  • +

    performance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:

    +
      +
    • +

      metrics, estimator, etc.

      +
    • +
    +
  • +
  • +

    tinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.

    +
  • +
+
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/man/gof_map.html b/docs/man/gof_map.html new file mode 100644 index 000000000..7a70d44b7 --- /dev/null +++ b/docs/man/gof_map.html @@ -0,0 +1,833 @@ + + + + + + +modelsummary: Data and Model Summaries in R – gof_map + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Data.frame used to clean up and format goodness-of-fit statistics

+

Description

+

By default, this data frame is passed to the ‘gof_map’ argument of the ‘modelsummary’ function. Users can modify this data frame to customize the list of statistics to display and their format. See example below.

+

Usage

+
gof_map
+
+

Format

+

data.frame with 4 columns of character data: raw, clean, fmt, omit

+

Examples

+
+
library(modelsummary)
+
+if (identical(Sys.getenv("pkgdown"),  "true")) {
+
+library(modelsummary)
+mod <- lm(wt ~ drat, data = mtcars)
+gm <- modelsummary::gof_map
+gm$omit[gm$raw == 'deviance'] <- FALSE
+gm$fmt[gm$raw == 'r.squared'] <- "%.5f"
+modelsummary(mod, gof_map = gm)
+}
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/modelplot.html b/docs/man/modelplot.html new file mode 100644 index 000000000..e004ca996 --- /dev/null +++ b/docs/man/modelplot.html @@ -0,0 +1,1160 @@ + + + + + + +modelsummary: Data and Model Summaries in R – modelplot + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Model Summary Plots with Estimates and Confidence Intervals

+

Description

+

Dot-Whisker plot of coefficient estimates with confidence intervals. For more information, see the Details and Examples sections below, and the vignettes on the modelsummary website: https://modelsummary.com/

+

Usage

+
modelplot(
+  models,
+  conf_level = 0.95,
+  coef_map = NULL,
+  coef_omit = NULL,
+  coef_rename = NULL,
+  vcov = NULL,
+  exponentiate = FALSE,
+  add_rows = NULL,
+  facet = FALSE,
+  draw = TRUE,
+  background = NULL,
+  ...
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+models + +

a model, (named) list of models, or nested list of models.

+
    +
  • +

    Single model: modelsummary(model)

    +
  • +
  • +

    Unnamed list of models: modelsummary(list(model1, model2))

    +
      +
    • +

      Models are labelled automatically. The default label style can be altered by setting a global option. See below.

      +
    • +
    +
  • +
  • +

    Named list of models: modelsummary(list(“A”=model1, “B”=model2))

    +
      +
    • +

      Models are labelled using the list names.

      +
    • +
    +
  • +
  • +

    Nested list of models:

    +
      +
    • +

      When using the shape argument with "rbind", "rcollapse", or "cbind" values, models can be a nested list of models to display "panels" or "stacks" of regression models. See the shape argument documentation and examples below.

      +
    • +
    +
  • +
+
+conf_level + +numeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models. +
+coef_map + +character vector. Subset, rename, and reorder coefficients. Coefficients omitted from this vector are omitted from the table. The order of the vector determines the order of the table. coef_map can be a named or an unnamed character vector. If coef_map is a named vector, its values define the labels that must appear in the table, and its names identify the original term names stored in the model object: c(“hp:mpg”=“HPxM/G”). See Examples section below. +
+coef_omit + +

integer vector or regular expression to identify which coefficients to omit (or keep) from the table. Positive integers determine which coefficients to omit. Negative integers determine which coefficients to keep. A regular expression can be used to omit coefficients, and perl-compatible "negative lookaheads" can be used to specify which coefficients to keep in the table. Examples:

+
    +
  • +

    c(2, 3, 5): omits the second, third, and fifth coefficients.

    +
  • +
  • +

    c(-2, -3, -5): negative values keep the second, third, and fifth coefficients.

    +
  • +
  • +

    “ei”: omit coefficients matching the "ei" substring.

    +
  • +
  • +

    “^Volume$”: omit the "Volume" coefficient.

    +
  • +
  • +

    “ei|rc”: omit coefficients matching either the "ei" or the "rc" substrings.

    +
  • +
  • +

    “^(?!Vol)”: keep coefficients starting with "Vol" (inverse match using a negative lookahead).

    +
  • +
  • +

    “^(?!.*ei)“: keep coefficients matching the”ei" substring.

    +
  • +
  • +

    “^(?!.ei|.pt)”: keep coefficients matching either the "ei" or the "pt" substrings.

    +
  • +
  • +

    See the Examples section below for complete code.

    +
  • +
+
+coef_rename + +

logical, named or unnamed character vector, or function

+
    +
  • +

    Logical: TRUE renames variables based on the "label" attribute of each column. See the Example section below.

    +
  • +
  • +

    Unnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.

    +
  • +
  • +

    Named character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c("hp:mpg"="hp X mpg")

    +
  • +
  • +

    Function: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)

    +
  • +
+
+vcov + +

robust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):

+
    +
  • +

    NULL returns the default uncertainty estimates of the model object

    +
  • +
  • +

    string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (), but it is safer to define your own custom functions as described in the next bullet.

    +
  • +
  • +

    function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).

    +
  • +
  • +

    formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).

    +
  • +
  • +

    named list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.

    +
  • +
  • +

    a named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.

    +
  • +
+
+exponentiate + +TRUE, FALSE, or logical vector of length equal to the number of models. If TRUE, the estimate, conf.low, and conf.high statistics are exponentiated, and the std.error is transformed to exp(estimate)*std.error. +
+add_rows + +a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. +
+facet + +TRUE or FALSE. When the ‘models’ argument includes several model objects, TRUE draws terms in separate facets, and FALSE draws terms side-by-side (dodged). +
+draw + +TRUE returns a ‘ggplot2’ object, FALSE returns the data.frame used to draw the plot. +
+background + +A list of ‘ggplot2’ geoms to add to the background of the plot. This is especially useful to display annotations "behind" the ‘geom_pointrange’ that ‘modelplot’ draws. +
+ + +

all other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.

+
    +
  • +

    parameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:

    +
      +
    • +

      standardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.

      +
    • +
    +
  • +
  • +

    performance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:

    +
      +
    • +

      metrics, estimator, etc.

      +
    • +
    +
  • +
  • +

    tinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.

    +
  • +
+

Examples

+
+
library(modelsummary)
+
+library(modelsummary)
+
+# single model
+mod <- lm(hp ~ vs + drat, mtcars)
+modelplot(mod)
+
+
+

+
+
+
+
# omit terms with string matches or regexes
+modelplot(mod, coef_omit = 'Interc')
+
+
+

+
+
+
+
# rename, reorder and subset with 'coef_map'
+cm <- c('vs' = 'V-shape engine',
+  'drat' = 'Rear axle ratio')
+modelplot(mod, coef_map = cm)
+
+
+

+
+
+
+
# several models
+models <- list()
+models[['Small model']] <- lm(hp ~ vs, mtcars)
+models[['Medium model']] <- lm(hp ~ vs + factor(cyl), mtcars)
+models[['Large model']] <- lm(hp ~ vs + drat + factor(cyl), mtcars)
+modelplot(models)
+
+
+

+
+
+
+
# add_rows: add an empty reference category
+
+mod <- lm(hp ~ factor(cyl), mtcars)
+
+add_rows = data.frame(
+  term = "factory(cyl)4",
+  model = "(1)",
+  estimate = NA)
+attr(add_rows, "position") = 3
+modelplot(mod, add_rows = add_rows)
+
+
+

+
+
+
+
# customize your plots with 'ggplot2' functions
+library(ggplot2)
+
+modelplot(models) +
+  scale_color_brewer(type = 'qual') +
+  theme_classic()
+
+
+

+
+
+
+
# pass arguments to 'geom_pointrange' through the ... ellipsis
+modelplot(mod, color = 'red', size = 1, fatten = .5)
+
+
+

+
+
+
+
# add geoms to the background, behind geom_pointrange
+b <- list(geom_vline(xintercept = 0, color = 'orange'),
+  annotate("rect", alpha = .1,
+    xmin = -.5, xmax = .5,
+    ymin = -Inf, ymax = Inf),
+  geom_point(aes(y = term, x = estimate), alpha = .3,
+    size = 10, color = 'red', shape = 'square'))
+modelplot(mod, background = b)
+
+
+

+
+
+
+
# logistic regression example
+df <- as.data.frame(Titanic)
+mod_titanic <- glm(
+  Survived ~ Class + Sex,
+  family = binomial,
+  weight = Freq,
+  data = df
+)
+
+# displaying odds ratio using a log scale
+modelplot(mod_titanic, exponentiate = TRUE) +
+  scale_x_log10() +
+  xlab("Odds Ratios and 95% confidence intervals")
+
+
+

+
+
+
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-1.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-1.png new file mode 100644 index 000000000..68333e002 Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-1.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-2.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-2.png new file mode 100644 index 000000000..33457c0a3 Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-2.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-3.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-3.png new file mode 100644 index 000000000..5c0e8307e Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-3.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-4.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-4.png new file mode 100644 index 000000000..fcfd5727c Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-4.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-5.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-5.png new file mode 100644 index 000000000..abf6c1542 Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-5.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-6.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-6.png new file mode 100644 index 000000000..b92abffe3 Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-6.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-7.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-7.png new file mode 100644 index 000000000..656755912 Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-7.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-8.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-8.png new file mode 100644 index 000000000..8f4d0e9ec Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-8.png differ diff --git a/docs/man/modelplot_files/figure-html/unnamed-chunk-1-9.png b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-9.png new file mode 100644 index 000000000..f8ddfdc81 Binary files /dev/null and b/docs/man/modelplot_files/figure-html/unnamed-chunk-1-9.png differ diff --git a/docs/man/modelsummary.html b/docs/man/modelsummary.html new file mode 100644 index 000000000..e6b0a00ff --- /dev/null +++ b/docs/man/modelsummary.html @@ -0,0 +1,9903 @@ + + + + + + +modelsummary: Data and Model Summaries in R – modelsummary + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Model Summary Tables

+

Description

+

Create beautiful and customizable tables to summarize several statistical models side-by-side. This function supports dozens of statistical models, and it can produce tables in HTML, LaTeX, Word, Markdown, Typst, PDF, PowerPoint, Excel, RTF, JPG, or PNG. The appearance of the tables can be customized extensively by specifying the output argument, and by using functions from one of the supported table customization packages: tinytable, kableExtra, gt, flextable, huxtable, DT. For more information, see the Details and Examples sections below, and the vignettes on the modelsummary website: https://modelsummary.com/

+

Usage

+
modelsummary(
+  models,
+  output = "default",
+  fmt = 3,
+  estimate = "estimate",
+  statistic = "std.error",
+  vcov = NULL,
+  conf_level = 0.95,
+  exponentiate = FALSE,
+  stars = FALSE,
+  shape = term + statistic ~ model,
+  coef_map = NULL,
+  coef_omit = NULL,
+  coef_rename = FALSE,
+  gof_map = NULL,
+  gof_omit = NULL,
+  gof_function = NULL,
+  group_map = NULL,
+  add_columns = NULL,
+  add_rows = NULL,
+  align = NULL,
+  notes = NULL,
+  title = NULL,
+  escape = TRUE,
+  ...
+)
+
+

Arguments

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+models + +

a model, (named) list of models, or nested list of models.

+
    +
  • +

    Single model: modelsummary(model)

    +
  • +
  • +

    Unnamed list of models: modelsummary(list(model1, model2))

    +
      +
    • +

      Models are labelled automatically. The default label style can be altered by setting a global option. See below.

      +
    • +
    +
  • +
  • +

    Named list of models: modelsummary(list(“A”=model1, “B”=model2))

    +
      +
    • +

      Models are labelled using the list names.

      +
    • +
    +
  • +
  • +

    Nested list of models:

    +
      +
    • +

      When using the shape argument with "rbind", "rcollapse", or "cbind" values, models can be a nested list of models to display "panels" or "stacks" of regression models. See the shape argument documentation and examples below.

      +
    • +
    +
  • +
+
+output + +

filename or object type (character string)

+
    +
  • +

    Supported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg

    +
  • +
  • +

    Supported object types: "default", "html", "markdown", "latex", "latex_tabular", "typst", "data.frame", "tinytable", "gt", "kableExtra", "huxtable", "flextable", "DT", "jupyter". The "modelsummary_list" value produces a lightweight object which can be saved and fed back to the modelsummary function.

    +
  • +
  • +

    The "default" output format can be set to "tinytable", "kableExtra", "gt", "flextable", "huxtable", "DT", or "markdown"

    +
      +
    • +

      If the user does not choose a default value, the packages listed above are tried in sequence.

      +
    • +
    • +

      Session-specific configuration: options(“modelsummary_factory_default” = “gt”)

      +
    • +
    • +

      Persistent configuration: config_modelsummary(output = “markdown”)

      +
    • +
    +
  • +
  • +

    Warning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.

    +
  • +
  • +

    LaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.

    +
  • +
+
+fmt + +

how to format numeric values: integer, user-supplied function, or modelsummary function.

+
    +
  • +

    Integer: Number of decimal digits

    +
  • +
  • +

    User-supplied functions:

    +
      +
    • +

      Any function which accepts a numeric vector and returns a character vector of the same length.

      +
    • +
    +
  • +
  • +

    modelsummary functions:

    +
      +
    • +

      fmt = fmt_significant(2): Two significant digits (at the term-level)

      +
    • +
    • +

      fmt = fmt_decimal(digits = 2, pdigits = 3): Decimal digits for estimate and p values

      +
    • +
    • +

      fmt = fmt_sprintf(“%.3f”): See ?sprintf

      +
    • +
    • +

      fmt = fmt_term(“(Intercept)” = 1, “X” = 2): Format terms differently

      +
    • +
    • +

      fmt = fmt_statistic(“estimate” = 1, “r.squared” = 6): Format statistics differently.

      +
    • +
    • +

      fmt = fmt_identity(): unformatted raw values

      +
    • +
    +
  • +
  • +

    string:

    +
  • +
  • +

    Note on LaTeX output: To ensure proper typography, all numeric entries are enclosed in the command, which requires the siunitx package to be loaded in the LaTeX preamble. This behavior can be altered with global options. See the ‘Details’ section.

    +
  • +
+
+estimate + +

a single string or a character vector of length equal to the number of models. Valid entries include any column name of the data.frame produced by get_estimates(model), and strings with curly braces compatible with the glue package format. Examples:

+
    +
  • +

    “estimate”

    +
  • +
  • +

    “{estimate} ({std.error}){stars}”

    +
  • +
  • +

    “{estimate} [{conf.low}, {conf.high}]”

    +
  • +
+
+statistic + +

vector of strings or glue strings which select uncertainty statistics to report vertically below the estimate. NULL omits all uncertainty statistics.

+
    +
  • +

    "conf.int", "std.error", "statistic", "p.value", "conf.low", "conf.high", or any column name produced by get_estimates(model)

    +
  • +
  • +

    glue package strings with braces, with or without R functions, such as:

    +
      +
    • +

      “{p.value} [{conf.low}, {conf.high}]”

      +
    • +
    • +

      “Std.Error: {std.error}”

      +
    • +
    • +

      “{exp(estimate) * std.error}”

      +
    • +
    • +

      Numbers are automatically rounded and converted to strings. To apply functions to their numeric values, as in the last glue example, users must set fmt=NULL.

      +
    • +
    • +

      Parentheses are added automatically unless the string includes glue curly braces {}.

      +
    • +
    +
  • +
  • +

    Notes:

    +
      +
    • +

      The names of the statistic are used a column names when using the shape argument to display statistics as columns:

      +
        +
      • +

        statistic=c(“p”=“p.value”, “[”=”conf.low”, ”]”=“conf.high”)

        +
      • +
      +
    • +
    • +

      Some statistics are not supported for all models. See column names in get_estimates(model), and visit the website to learn how to add custom statistics.

      +
    • +
    +
  • +
+
+vcov + +

robust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):

+
    +
  • +

    NULL returns the default uncertainty estimates of the model object

    +
  • +
  • +

    string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (), but it is safer to define your own custom functions as described in the next bullet.

    +
  • +
  • +

    function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).

    +
  • +
  • +

    formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).

    +
  • +
  • +

    named list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.

    +
  • +
  • +

    a named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.

    +
  • +
+
+conf_level + +numeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models. +
+exponentiate + +TRUE, FALSE, or logical vector of length equal to the number of models. If TRUE, the estimate, conf.low, and conf.high statistics are exponentiated, and the std.error is transformed to exp(estimate)*std.error. +
+stars + +

to indicate statistical significance

+
    +
  • +

    FALSE (default): no significance stars.

    +
  • +
  • +

    TRUE: +=.1, =.05, =.01, =0.001

    +
  • +
  • +

    Named numeric vector for custom stars such as c(’*’ = .1, ‘+’ = .05)

    +
  • +
  • +

    Note: a legend will not be inserted at the bottom of the table when the estimate or statistic arguments use "glue strings" with stars.

    +
  • +
+
+shape + +

NULL, formula, or string which determines the shape of a table.

+
    +
  • +

    NULL: Default shape with terms in rows and models in columns.

    +
  • +
  • +

    Formula: The left side determines what appears on rows, and the right side determines what appears on columns. The formula can include one or more group identifier(s) to display related terms together, which can be useful for models with multivariate outcomes or grouped coefficients (See examples section below). The group identifier(s) must be column names produced by: get_estimates(model). The group identifier(s) can be combined with the term identifier in a single column by using the colon to represent an interaction. If an incomplete formula is supplied (e.g., ~statistic), modelsummary tries to complete it automatically. Goodness-of-fit statistics are only appended to the bottom of the table when model is on the right hand side of the formula (i.e., columns). Potential shape values include:

    +
      +
    • +

      term + statistic ~ model: default

      +
    • +
    • +

      term ~ model + statistic: statistics in separate columns

      +
    • +
    • +

      model + statistic ~ term: models in rows and terms in columns

      +
    • +
    • +

      term + response + statistic ~ model: term and group id in separate columns

      +
    • +
    • +

      term : response + statistic ~ model: term and group id in a single column

      +
    • +
    • +

      term ~ response

      +
    • +
    +
  • +
  • +

    String: "cbind", "rbind", "rcollapse"

    +
      +
    • +

      "cbind": side-by-side models with autmoatic spanning column headers to group models (tinytable only feature).

      +
    • +
    • +

      "rbind" or "rcollapse": "panels" or "stacks" of regression models.

      +
    • +
    • +

      the models argument must be a (potentially named) nested list of models.

      +
    • +
    +
      +
    • +

      Unnamed nested list with 2 panels: list(list(model1, model2), list(model3, model4))

      +
    • +
    • +

      Named nested list with 2 panels: list(“Panel A” = list(model1, model2), “Panel B” = list(model3, model4))

      +
    • +
    • +

      Named panels and named models: list(“Panel A” = list(“(I)” = model1, “(II)” = model2), “Panel B” = list(“(I)” = model3, “(II)” = model4))

      +
    • +
    +
      +
    • +

      "rbind": Bind the rows of independent regression tables

      +
    • +
    • +

      "rcollapse": Bind the rows of regression tables and create a panel at the bottom where we "collapse" goodness-of-fit statistics which are identical across models.

      +
    • +
    +
  • +
+
+coef_map + +character vector. Subset, rename, and reorder coefficients. Coefficients omitted from this vector are omitted from the table. The order of the vector determines the order of the table. coef_map can be a named or an unnamed character vector. If coef_map is a named vector, its values define the labels that must appear in the table, and its names identify the original term names stored in the model object: c(“hp:mpg”=“HPxM/G”). See Examples section below. +
+coef_omit + +

integer vector or regular expression to identify which coefficients to omit (or keep) from the table. Positive integers determine which coefficients to omit. Negative integers determine which coefficients to keep. A regular expression can be used to omit coefficients, and perl-compatible "negative lookaheads" can be used to specify which coefficients to keep in the table. Examples:

+
    +
  • +

    c(2, 3, 5): omits the second, third, and fifth coefficients.

    +
  • +
  • +

    c(-2, -3, -5): negative values keep the second, third, and fifth coefficients.

    +
  • +
  • +

    “ei”: omit coefficients matching the "ei" substring.

    +
  • +
  • +

    “^Volume$”: omit the "Volume" coefficient.

    +
  • +
  • +

    “ei|rc”: omit coefficients matching either the "ei" or the "rc" substrings.

    +
  • +
  • +

    “^(?!Vol)”: keep coefficients starting with "Vol" (inverse match using a negative lookahead).

    +
  • +
  • +

    “^(?!.*ei)“: keep coefficients matching the”ei" substring.

    +
  • +
  • +

    “^(?!.ei|.pt)”: keep coefficients matching either the "ei" or the "pt" substrings.

    +
  • +
  • +

    See the Examples section below for complete code.

    +
  • +
+
+coef_rename + +

logical, named or unnamed character vector, or function

+
    +
  • +

    Logical: TRUE renames variables based on the "label" attribute of each column. See the Example section below.

    +
  • +
  • +

    Unnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.

    +
  • +
  • +

    Named character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c("hp:mpg"="hp X mpg")

    +
  • +
  • +

    Function: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)

    +
  • +
+
+gof_map + +

rename, reorder, and omit goodness-of-fit statistics and other model information. This argument accepts 4 types of values:

+
    +
  • +

    NULL (default): the modelsummary::gof_map dictionary is used for formatting, and all unknown statistic are included.

    +
  • +
  • +

    character vector: "all", "none", or a vector of statistics such as c(“rmse”, “nobs”, “r.squared”). Elements correspond to colnames in the data.frame produced by get_gof(model). The modelsummary::gof_map default dictionary is used to format and rename statistics.

    +
  • +
  • +

    NA: excludes all statistics from the bottom part of the table.

    +
  • +
  • +

    data.frame with 3 columns named "raw", "clean", "fmt". Unknown statistics are omitted. See the ‘Examples’ section below. The fmt column in this data frame only accepts integers. For more flexibility, use a list of lists, as described in the next bullet.

    +
  • +
  • +

    list of lists, each of which includes 3 elements named "raw", "clean", "fmt". Unknown statistics are omitted. See the ‘Examples section below’.

    +
  • +
+
+gof_omit + +

string regular expression (perl-compatible) used to determine which statistics to omit from the bottom section of the table. A "negative lookahead" can be used to specify which statistics to keep in the table. Examples:

+
    +
  • +

    “IC”: omit statistics matching the "IC" substring.

    +
  • +
  • +

    “BIC|AIC”: omit statistics matching the "AIC" or "BIC" substrings.

    +
  • +
  • +

    “^(?!.*IC)“: keep statistics matching the”IC" substring.

    +
  • +
+
+gof_function + +function which accepts a model object in the model argument and returns a 1-row data.frame with one custom goodness-of-fit statistic per column. +
+group_map + +named or unnamed character vector. Subset, rename, and reorder coefficient groups specified a grouping variable specified in the shape argument formula. This argument behaves like coef_map. +
+add_columns + +a data.frame (or tibble) with the same number of rows as #’ your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the columns positions. See Examples section below. +
+add_rows + +a data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a "position" attribute of integers to set the row positions. See Examples section below. +
+align + +

A string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.

+
    +
  • +

    "l": left-aligned column

    +
  • +
  • +

    "c": centered column

    +
  • +
  • +

    "r": right-aligned column

    +
  • +
  • +

    "d": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.

    +
  • +
+
+notes + +list or vector of notes to append to the bottom of the table. +
+title + +string +
+escape + +boolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE) +
+ + +

all other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.

+
    +
  • +

    parameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:

    +
      +
    • +

      standardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.

      +
    • +
    +
  • +
  • +

    performance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:

    +
      +
    • +

      metrics, estimator, etc.

      +
    • +
    +
  • +
  • +

    tinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.

    +
  • +
+

Details

+

+output +

+

The modelsummary_list output is a lightweight format which can be used to save model results, so they can be fed back to modelsummary later to avoid extracting results again.

+

When a file name with a valid extension is supplied to the output argument, the table is written immediately to file. If you want to customize your table by post-processing it with an external package, you need to choose a different output format and saving mechanism. Unfortunately, the approach differs from package to package:

+
    +
  • +

    tinytable: set output=“tinytable”, post-process your table, and use the tinytable::save_tt function.

    +
  • +
  • +

    gt: set output=“gt”, post-process your table, and use the gt::gtsave function.

    +
  • +
  • +

    kableExtra: set output to your destination format (e.g., "latex", "html", "markdown"), post-process your table, and use kableExtra::save_kable function.

    +
  • +
+

+vcov +

+

To use a string such as "robust" or "HC0", your model must be supported by the sandwich package. This includes objects such as: lm, glm, survreg, coxph, mlogit, polr, hurdle, zeroinfl, and more.

+

NULL, "classical", "iid", and "constant" are aliases which do not modify uncertainty estimates and simply report the default standard errors stored in the model object.

+

One-sided formulas such as ~clusterid are passed to the sandwich::vcovCL function.

+

Matrices and functions producing variance-covariance matrices are first passed to lmtest. If this does not work, modelsummary attempts to take the square root of the diagonal to adjust "std.error", but the other uncertainty estimates are not be adjusted.

+

Numeric vectors are formatted according to fmt and placed in brackets. Character vectors printed as given, without parentheses.

+

If your model type is supported by the lmtest package, the vcov argument will try to use that package to adjust all the uncertainty estimates, including "std.error", "statistic", "p.value", and "conf.int". If your model is not supported by lmtest, only the "std.error" will be adjusted by, for example, taking the square root of the matrix’s diagonal.

+

Value

+

a regression table in a format determined by the output argument.

+

Global Options

+

The behavior of modelsummary can be modified by setting global options. For example:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
+

The rest of this section describes each of the options above.

+

+Model labels: default column names +

+

These global option changes the style of the default column headers:

+
    +
  • +

    options(modelsummary_model_labels = “roman”)

    +
  • +
  • +

    options(modelsummary_panel_labels = “roman”)

    +
  • +
+

The supported styles are: "model", "panel", "arabic", "letters", "roman", "(arabic)", "(letters)", "(roman)"

+

The panel-specific option is only used when shape=“rbind”

+

+Table-making packages +

+

modelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:

+

options(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)

+

+Table themes +

+

Change the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html

+
    +
  • +

    modelsummary_theme_gt

    +
  • +
  • +

    modelsummary_theme_kableExtra

    +
  • +
  • +

    modelsummary_theme_huxtable

    +
  • +
  • +

    modelsummary_theme_flextable

    +
  • +
  • +

    modelsummary_theme_dataframe

    +
  • +
+

+Model extraction functions +

+

modelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:

+

options(modelsummary_get = “easystats”)

+

options(modelsummary_get = “broom”)

+

options(modelsummary_get = “all”)

+

+Formatting numeric entries +

+

By default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:

+

options(modelsummary_format_numeric_latex = “plain”)

+

options(modelsummary_format_numeric_latex = “mathmode”)

+

A similar option can be used to display numerical entries using MathJax in HTML tables:

+

options(modelsummary_format_numeric_html = “mathjax”)

+

+LaTeX preamble +

+

When creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.

+

[3]{}

+

Parallel computation

+

It can take a long time to compute and extract summary statistics from certain models (e.g., Bayesian). In those cases, users can parallelize the process. Since parallelization occurs at the model level, no speedup is available for tables with a single model. Users on mac or linux can launch parallel computation using the built-in parallel package. All they need to do is supply a mc.cores argument which will be pushed forward to the parallel::mclapply function:

+
+
modelsummary(model_list, mc.cores = 5)
+
+
+

All users can also use the future.apply package to parallelize model summaries. For example, to use 4 cores to extract results:

+
+
library(future.apply)
+plan(multicore, workers = 4)
+options("modelsummary_future" = TRUE)
+modelsummary(model_list)
+
+
+

Note that the "multicore" plan only parallelizes under mac or linux. Windows users can use plan(multisession) instead. However, note that the first time modelsummary() is called under multisession can be a fair bit longer, because of extra costs in passing data to and loading required packages on to workers. Subsequent calls to modelsummary() will often be much faster.

+

Some users have reported difficult to reproduce errors when using the future package with some packages. The future parallelization in modelsummary can be disabled by calling:

+

options(“modelsummary_future” = FALSE)

+

References

+

Arel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’

+

Examples

+
+
library(modelsummary)
+
+
+# The `modelsummary` website includes \emph{many} examples and tutorials:
+# https://modelsummary.com
+
+library(modelsummary)
+
+# load data and estimate models
+utils::data(trees)
+models <- list()
+models[['Bivariate']] <- lm(Girth ~ Height, data = trees)
+models[['Multivariate']] <- lm(Girth ~ Height + Volume, data = trees)
+
+# simple table
+modelsummary(models)
+
+ + + + + +tinytable_mcj4zhgw5up1bpuiazvv + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
Volume 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# statistic
+modelsummary(models, statistic = NULL)
+
+ + + + + +tinytable_qrrm1ns1xhp54009wgtz + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
Height 0.256 -0.045
Volume 0.195
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models, statistic = 'p.value')
+
+ + + + + +tinytable_he4qy7ao5dkgshldjxv8 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(0.308)( +
Height 0.256 -0.045
(0.003)(0.119)
Volume 0.195
( +
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models, statistic = 'statistic')
+
+ + + + + +tinytable_jv2mi0vsnbljzcxn55oe + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(-1.038)(5.482)
Height 0.256 -0.045
(3.272) (-1.609)
Volume 0.195
(17.816)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061 -35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models, statistic = 'conf.int', conf_level = 0.99)
+
+ + + + + +tinytable_qhae4g99mpkj94vw8zz2 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
[-22.617, 10.240][5.364, 16.269]
Height 0.256 -0.045
[0.040, 0.471] [-0.124, 0.033]
Volume 0.195
[0.165, 0.225]
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061 -35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models, statistic = c("t = {statistic}",
+                                   "se = {std.error}",
+                                   "conf.int"))
+
+ + + + + +tinytable_bd2w1unh5si2ob1nwap9 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
t = -1.038 t = 5.482
se = 5.960 se = 1.973
[-18.378, 6.002][6.774, 14.858]
Height 0.256 -0.045
t = 3.272 t = -1.609
se = 0.078 se = 0.028
[0.096, 0.416] [-0.103, 0.012]
Volume 0.195
t = 17.816
se = 0.011
[0.173, 0.218]
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061 -35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# estimate
+modelsummary(models,
+  statistic = NULL,
+  estimate = "{estimate} [{conf.low}, {conf.high}]")
+
+ + + + + +tinytable_idwa3y8zpe8oumq9dmbj + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 [-18.378, 6.002]10.816 [6.774, 14.858]
Height 0.256 [0.096, 0.416] -0.045 [-0.103, 0.012]
Volume 0.195 [0.173, 0.218]
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061 -35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models,
+  estimate = c("{estimate}{stars}",
+               "{estimate} ({std.error})"))
+
+ + + + + +tinytable_pkh9uv1j7tevhruib11c + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816 (1.973)
(5.960)(1.973)
Height 0.256**-0.045 (0.028)
(0.078)(0.028)
Volume 0.195 (0.011)
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# vcov
+modelsummary(models, vcov = "robust")
+
+ + + + + +tinytable_dohd2tu9jincrqw9navw + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(6.717)(2.544)
Height 0.256 -0.045
(0.090)(0.035)
Volume 0.195
(0.014)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 8.021 100.427
RMSE 2.64 0.75
Std.Errors HC3 HC3
+
+ + +
+
modelsummary(models, vcov = list("classical", "stata"))
+
+ + + + + +tinytable_h4yy74l84znfd2ulobjw + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(2.261)
Height 0.256 -0.045
(0.078)(0.031)
Volume 0.195
(0.012)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 151.435
RMSE 2.64 0.75
Std.Errors IID HC1
+
+ + +
+
modelsummary(models, vcov = sandwich::vcovHC)
+
+ + + + + +tinytable_x9abw2if38t63xnw5z4c + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(6.717)(2.544)
Height 0.256 -0.045
(0.090)(0.035)
Volume 0.195
(0.014)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
RMSE 2.64 0.75
Std.Errors Custom Custom
+
+ + +
+
modelsummary(models,
+  vcov = list(stats::vcov, sandwich::vcovHC))
+
+ + + + + +tinytable_zx024ku0vvosj0cx9h3e + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(2.544)
Height 0.256 -0.045
(0.078)(0.035)
Volume 0.195
(0.014)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
RMSE 2.64 0.75
Std.Errors Custom Custom
+
+ + +
+
modelsummary(models,
+  vcov = list(c("(Intercept)"="", "Height"="!"),
+              c("(Intercept)"="", "Height"="!", "Volume"="!!")))
+
+ + + + + +tinytable_gs5awfdrsxdfx7mp2ve7 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
Height 0.256 -0.045
! !
Volume 0.195
!!
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
RMSE 2.64 0.75
Std.Errors Custom Custom
+
+ + +
+
# vcov with custom names
+modelsummary(
+  models,
+  vcov = list("Stata Corp" = "stata",
+              "Newey Lewis & the News" = "NeweyWest"))
+
+ + + + + +tinytable_60fu490ojr1t5pblfiij + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(6.171) (1.839)
Height 0.256 -0.045
(0.083) (0.022)
Volume 0.195
(0.007)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061 -35.116
RMSE 2.64 0.75
Std.Errors Stata CorpNewey Lewis & the News
+
+ + +
+
# fmt
+mod <- lm(mpg ~ hp + drat + qsec, data = mtcars)
+
+modelsummary(mod, fmt = 3)
+
+ + + + + +tinytable_x3h0ityo4f865lgcnncl + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)17.737
(13.020)
hp -0.058
(0.014)
drat 4.429
(1.292)
qsec -0.284
(0.489)
Num.Obs. 32
R2 0.744
R2 Adj. 0.717
AIC 171.1
BIC 178.5
Log.Lik. -80.561
F 27.161
RMSE 3.00
+
+ + +
+ +
+ + + + + +tinytable_j6f4s5owmade787l5bsb + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)17.7
(13.0)
hp -0.0580
(0.0142)
drat 4.43
(1.29)
qsec -0.284
(0.489)
Num.Obs. 32
R2 0.744
R2 Adj. 0.717
AIC 171.1
BIC 178.5
Log.Lik. -80.561
F 27.161
RMSE 3.00
+
+ + +
+
modelsummary(mod, fmt = NULL)
+
+ + + + + +tinytable_f0exllns2gcztktcjygr + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)17.7366200480466
(13.0197907534221)
hp -0.057972987581075
(0.014208609097443)
drat 4.42875344653986
(1.29169225236228)
qsec -0.284074290906574
(0.489229280152)
Num.Obs. 32
R2 0.744
R2 Adj. 0.717
AIC 171.1
BIC 178.5
Log.Lik. -80.561
F 27.161
RMSE 3.00
+
+ + +
+
modelsummary(mod, fmt = fmt_decimal(4))
+
+ + + + + +tinytable_9uvqs6k8qkl5zmtdi5cr + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)17.7366
(13.0198)
hp -0.0580
(0.0142)
drat 4.4288
(1.2917)
qsec -0.2841
(0.4892)
Num.Obs. 32
R2 0.744
R2 Adj. 0.717
AIC 171.1
BIC 178.5
Log.Lik. -80.561
F 27.161
RMSE 3.00
+
+ + +
+
modelsummary(mod, fmt = fmt_sprintf("%.5f"))
+
+ + + + + +tinytable_skia0w0qpih8cryrs5x7 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)17.73662
(13.01979)
hp -0.05797
(0.01421)
drat 4.42875
(1.29169)
qsec -0.28407
(0.48923)
Num.Obs. 32
R2 0.744
R2 Adj. 0.717
AIC 171.1
BIC 178.5
Log.Lik. -80.561
F 27.161
RMSE 3.00
+
+ + +
+
modelsummary(mod, fmt = fmt_statistic(estimate = 4, conf.int = 1), statistic = "conf.int")
+
+ + + + + +tinytable_ye03yw1s7yjnv916nfq1 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)17.7366
[-8.9, 44.4]
hp -0.0580
[-0.1, 0.0]
drat 4.4288
[1.8, 7.1]
qsec -0.2841
[-1.3, 0.7]
Num.Obs. 32
R2 0.744
R2 Adj. 0.717
AIC 171.1
BIC 178.5
Log.Lik. -80.561
F 27.161
RMSE 3.00
+
+ + +
+
modelsummary(mod, fmt = fmt_term(hp = 4, drat = 1, default = 2))
+
+ + + + + +tinytable_f3jackzt6fgrtnoisuf6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)17.74
(13.02)
hp -0.0580
(0.0142)
drat 4.4
(1.3)
qsec -0.28
(0.49)
Num.Obs. 32
R2 0.744
R2 Adj. 0.717
AIC 171.1
BIC 178.5
Log.Lik. -80.561
F 27.161
RMSE 3.00
+
+ + +
+
m <- lm(mpg ~ I(hp * 1000) + drat, data = mtcars)
+f <- function(x) format(x, digits = 3, nsmall = 2, scientific = FALSE, trim = TRUE)
+modelsummary(m, fmt = f, gof_map = NA)
+
+ + + + + +tinytable_2w2n9juxyb78dfqqqc09 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept) 10.7898612
(5.07775160)
I(hp * 1000)-0.0000518
(0.00000929)
drat 4.6981578
(1.19163348)
+
+ + +
+
# coef_rename
+modelsummary(models, coef_rename = c('Volume' = 'Large', 'Height' = 'Tall'))
+
+ + + + + +tinytable_4pwqwj6b87mwuxkuka2v + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Tall 0.256 -0.045
(0.078)(0.028)
Large 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models, coef_rename = toupper)
+
+ + + + + +tinytable_368s8x0z4lodkykk2jsj + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(INTERCEPT)-6.188 10.816
(5.960)(1.973)
HEIGHT 0.256 -0.045
(0.078)(0.028)
VOLUME 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models, coef_rename = coef_rename)
+
+ + + + + +tinytable_36nrj7aeah44jz3si96q + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
Volume 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# coef_rename = TRUE for variable labels
+datlab <- mtcars
+datlab$cyl <- factor(datlab$cyl)
+attr(datlab$hp, "label") <- "Horsepower"
+attr(datlab$cyl, "label") <- "Cylinders"
+modlab <- lm(mpg ~ hp * drat + cyl, data = datlab)
+modelsummary(modlab, coef_rename = TRUE)
+
+ + + + + +tinytable_jd3dgp5uqqoiirbwh47q + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept) 14.850
(11.923)
Horsepower -0.011
(0.082)
drat 3.612
(3.019)
Cylinders [6] -4.091
(1.881)
Cylinders [8] -5.019
(3.056)
Horsepower × drat-0.006
(0.021)
Num.Obs. 32
R2 0.784
R2 Adj. 0.742
AIC 169.7
BIC 180.0
Log.Lik. -77.860
F 18.871
RMSE 2.76
+
+ + +
+
# coef_rename: unnamed vector of length equal to the number of terms in the final table
+m <- lm(hp ~ mpg + factor(cyl), data = mtcars)
+modelsummary(m, coef_omit = -(3:4), coef_rename = c("Cyl 6", "Cyl 8"))
+
+ + + + + +tinytable_8yhhdupm1wl2yboqg1ru + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
Cyl 6 16.623
(23.197)
Cyl 8 88.105
(28.819)
Num.Obs.32
R2 0.737
R2 Adj. 0.709
AIC 327.7
BIC 335.0
Log.Lik.-158.831
F 26.122
RMSE 34.62
+
+ + +
+
# coef_map
+modelsummary(models, coef_map = c('Volume' = 'Large', 'Height' = 'Tall'))
+
+ + + + + +tinytable_jvpbqyxyspsg4mlxlv5s + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
Large 0.195
(0.011)
Tall 0.256 -0.045
(0.078)(0.028)
Num.Obs.31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik.-74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
modelsummary(models, coef_map = c('Volume', 'Height'))
+
+ + + + + +tinytable_cht3225tx0vqxyzy66z3 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
Volume 0.195
(0.011)
Height 0.256 -0.045
(0.078)(0.028)
Num.Obs.31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik.-74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# coef_omit: omit the first and second coefficients
+modelsummary(models, coef_omit = 1:2)
+
+ + + + + +tinytable_zg88j5z13olou34egikk + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
Volume 0.195
(0.011)
Num.Obs.31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik.-74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# coef_omit: omit coefficients matching one substring
+modelsummary(models, coef_omit = "ei", gof_omit = ".*")
+
+ + + + + +tinytable_aiuatsml2moa4l7samru + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Volume 0.195
(0.011)
+
+ + +
+
# coef_omit: omit a specific coefficient
+modelsummary(models, coef_omit = "^Volume$", gof_omit = ".*")
+
+ + + + + +tinytable_90yc5ohf513hvzx7jhep + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
+
+ + +
+
# coef_omit: omit coefficients matching either one of two substring
+#modelsummary(models, coef_omit = "ei|rc", gof_omit = ".*")
+
+# coef_omit: keep coefficients starting with a substring (using a negative lookahead)
+#modelsummary(models, coef_omit = "^(?!Vol)", gof_omit = ".*")
+
+# coef_omit: keep coefficients matching a substring
+modelsummary(models, coef_omit = "^(?!.*ei|.*pt)", gof_omit = ".*")
+
+ + + + + +tinytable_leo6hlsmpbh7w23dcxet + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
+
+ + +
+
# shape: multinomial model
+library(nnet)
+multi <- multinom(factor(cyl) ~ mpg + hp, data = mtcars, trace = FALSE) 
+
+# shape: term names and group ids in rows, models in columns
+modelsummary(multi, shape = response ~ model)
+
+ + + + + +tinytable_2x6f6mtmn6m96xomt61h + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
response(1)
(Intercept)60.500
(41.760)
88.400
(0.502)
mpg 6-83.069
(416.777)
8-120.167
(508.775)
hp 616.230
(81.808)
820.307
(87.777)
Num.Obs. 32
R2 1.000
R2 Adj. 0.971
AIC 12.0
BIC 20.8
RMSE 0.00
+
+ + +
+
# shape: term names and group ids in rows in a single column
+modelsummary(multi, shape = term : response ~ model)
+
+ + + + + +tinytable_qp9b1b3zy0ngjz4s1ixu + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept) 60.500
(41.760)
mpg 6 -83.069
(416.777)
hp 6 16.230
(81.808)
(Intercept) 88.400
(0.502)
mpg 8 -120.167
(508.775)
hp 8 20.307
(87.777)
Num.Obs. 32
R2 1.000
R2 Adj. 0.971
AIC 12.0
BIC 20.8
RMSE 0.00
+
+ + +
+
# shape: term names in rows and group ids in columns
+modelsummary(multi, shape = term ~ response:model)
+
+ + + + + +tinytable_kkvdw7jviuquvn5wqnzs + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
68
(Intercept)0.500 8.400
(41.760) (0.502)
mpg -83.069 -120.167
(416.777)(508.775)
hp 16.230 20.307
(81.808) (87.777)
Num.Obs. 32
R2 1.000
R2 Adj. 0.971
AIC 12.0
BIC 20.8
RMSE 0.00
+
+ + +
+
# shape = "rcollapse"
+panels <- list(
+    "Panel A: MPG" = list(
+        "A" = lm(mpg ~ hp, data = mtcars),
+        "B" = lm(mpg ~ hp + factor(gear), data = mtcars)),
+    "Panel B: Displacement" = list(
+        "A" = lm(disp ~ hp, data = mtcars),
+        "C" = lm(disp ~ hp + factor(gear), data = mtcars))
+)
+
+# shape = "cbind"
+modelsummary(panels, shape = "cbind")
+
+ + + + + +tinytable_i3nyohz4ryvw87xcdrvr + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Panel A: MPGPanel B: Displacement
ABA C
(Intercept) 30.099 27.882 20.992 112.093
(1.634)(2.109)(32.607)(34.704)
hp -0.068 -0.067 1.430 1.216
(0.010)(0.011)(0.202) (0.182)
factor(gear)4 2.635 -97.923
(1.552) (25.532)
factor(gear)5 6.575 -147.495
(1.643) (27.030)
Num.Obs. 32 32 32 32
R2 0.602 0.753 0.626 0.842
R2 Adj. 0.589 0.726 0.613 0.825
AIC 181.2 170.0 372.8 349.3
BIC 185.6 177.4 377.2 356.6
Log.Lik. -87.619-80.024-183.412-169.643
F 45.460 28.407 50.128 49.611
RMSE 3.74 2.95 74.64 48.54
+
+ + +
+
modelsummary(
+    panels,
+    shape = "rbind",
+    gof_map = c("nobs", "r.squared"))
+
+ + + + + +tinytable_8g8cbr2e6rkzqw58oxza + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ABC
(Intercept) 30.099 27.882
(1.634) (2.109)
hp -0.068 -0.067
(0.010) (0.011)
factor(gear)4 2.635
(1.552)
factor(gear)5 6.575
(1.643)
Num.Obs. 32 32
R2 0.602 0.753
(Intercept) 20.992 112.093
(32.607) (34.704)
hp 1.430 1.216
(0.202) (0.182)
factor(gear)4 -97.923
(25.532)
factor(gear)5 -147.495
(27.030)
Num.Obs. 32 32
R2 0.626 0.842
+
+ + +
+
# title
+modelsummary(models, title = 'This is the title')
+
+ + + + + +tinytable_4i850ve155sa8cck22rk + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
This is the title
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
Volume 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# title with LaTeX label (for numbering and referencing)
+modelsummary(models, title = 'This is the title \\label{tab:description}')
+
+ + + + + +tinytable_8m7o5gclykcsbtnqn7gh + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
This is the title \label{tab:description}
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
Volume 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# add_rows
+rows <- tibble::tribble(~term, ~Bivariate, ~Multivariate,
+  'Empty row', '-', '-',
+  'Another empty row', '?', '?')
+attr(rows, 'position') <- c(1, 3)
+modelsummary(models, add_rows = rows)
+
+ + + + + +tinytable_u2tqoc5p422bx49w9j60 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
Empty row - -
(Intercept) -6.188 10.816
Another empty row? ?
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
Volume 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# notes
+modelsummary(models, notes = list('A first note', 'A second note'))
+
+ + + + + +tinytable_0ghxu5xl138u2hrnedt4 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
A first note
A second note
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
Volume 0.195
(0.011)
Num.Obs. 31 31
R2 0.270 0.941
R2 Adj. 0.244 0.937
AIC 154.1 78.2
BIC 158.4 84.0
Log.Lik. -74.061-35.116
F 10.707 222.471
RMSE 2.64 0.75
+
+ + +
+
# gof_map: tribble
+library(tibble)
+gm <- tribble(
+  ~raw,        ~clean,      ~fmt,
+  "r.squared", "R Squared", 5)
+modelsummary(models, gof_map = gm)
+
+ + + + + +tinytable_3znxwmq3oulnxnzngn8k + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BivariateMultivariate
(Intercept)-6.188 10.816
(5.960)(1.973)
Height 0.256 -0.045
(0.078)(0.028)
Volume 0.195
(0.011)
R Squared 0.269650.94080
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/man/update_modelsummary.html b/docs/man/update_modelsummary.html new file mode 100644 index 000000000..efa8bffb6 --- /dev/null +++ b/docs/man/update_modelsummary.html @@ -0,0 +1,828 @@ + + + + + + + + + +modelsummary: Data and Model Summaries in R – update_modelsummary + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+

Update modelsummary and its dependencies

+
+

Description

+

Update modelsummary and its dependencies to the latest R-Universe or CRAN versions. The R session needs to be restarted after install.

+
+
+

Usage

+
update_modelsummary(source = "development")
+
+
+
+

Arguments

+ + + + + +
+source + +one of two strings: "development" or "cran" +
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml new file mode 100644 index 000000000..4e239856c --- /dev/null +++ b/docs/pkgdown.yml @@ -0,0 +1,3 @@ +urls: + reference: https://modelsummary.com/man + article: https://modelsummary.com/vignettes \ No newline at end of file diff --git a/docs/quarto_website.yml b/docs/quarto_website.yml new file mode 100644 index 000000000..aabe28d59 --- /dev/null +++ b/docs/quarto_website.yml @@ -0,0 +1,90 @@ +project: + type: website + output-dir: ../docs/ + +website: + title: "modelsummary: Data and Model Summaries in R" + page-navigation: true + + navbar: + background: "#eeeeee" + search: true + right: + - text: Get started + href: vignettes/get_started.qmd + - icon: github + href: $ALTDOC_PACKAGE_URL_GITHUB + aria-label: $ALTDOC_PACKAGE_NAME GitHub + sidebar: + collapse-level: 1 + contents: + - vignettes/get_started.qmd + - vignettes/datasummary.qmd + - vignettes/modelsummary.qmd + - vignettes/modelplot.qmd + - vignettes/modelsummary_extension.qmd + - vignettes/appearance.qmd + - section: "Functions" + contents: + - text: "`modelsummary`" + file: man/modelsummary.qmd + - text: "`modelplot`" + file: man/modelplot.qmd + - text: "`datasummary`" + file: man/datasummary.qmd + - text: "`datasummary_skim`" + file: man/datasummary_skim.qmd + - text: "`datsummary_balance`" + file: man/datasummary_balance.qmd + - text: "`datasummary_crosstab`" + file: man/datasummary_crosstab.qmd + - text: "`datasummary_correlation`" + file: man/datasummary_correlation.qmd + - section: "Formatting" + contents: + - text: "`fmt_decimal`" + file: man/fmt_decimal.qmd + - text: "`fmt_sci`" + file: man/fmt_sci.qmd + - text: "`fmt_significant`" + file: man/fmt_significant.qmd + - text: "`fmt_sprintf`" + file: man/fmt_sprintf.qmd + - text: "`fmt_statistic`" + file: man/fmt_statistic.qmd + - text: "`fmt_term`" + file: man/fmt_term.qmd + - section: "Utilities" + contents: + - text: "`get_estimates`" + file: man/get_estimates.qmd + - text: "`get_gof`" + file: man/get_gof.qmd + - text: "`coef_rename`" + file: man/coef_rename.qmd + - text: "`dvnames`" + file: man/dvnames.qmd + - text: "`gof_map`" + file: man/gof_map.qmd + - text: "`datasummary_correlation_format`" + file: man/datasummary_correlation_format.qmd + - text: "`config_modelsummary`" + file: man/config_modelsummary.qmd + - text: "`update_modelsummary`" + file: man/update_modelsummary.qmd + - $ALTDOC_NEWS + - $ALTDOC_CHANGELOG + - $ALTDOC_LICENSE + - $ALTDOC_LICENCE + - $ALTDOC_CODE_OF_CONDUCT + - $ALTDOC_CITATION + +format: + html: + toc: true + theme: + - flatly + - custom.scss + code-link: true + code-copy: true + code-overflow: scroll diff --git a/docs/search.json b/docs/search.json new file mode 100644 index 000000000..08e71e2c3 --- /dev/null +++ b/docs/search.json @@ -0,0 +1,1571 @@ +[ + { + "objectID": "index.html", + "href": "index.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "modelsummary creates tables and plots to present descriptive statistics and to summarize statistical models in R." + }, + { + "objectID": "index.html#what", + "href": "index.html#what", + "title": "modelsummary: Data and Model Summaries in R", + "section": "What?", + "text": "What?\nmodelsummary includes two families of functions:\n\nModel Summary\n\nmodelsummary: Regression tables with side-by-side models.\nmodelplot: Coefficient plots.\n\nData Summary\n\ndatasummary: Powerful tool to create (multi-level) cross-tabs and data summaries.\ndatasummary_crosstab: Cross-tabulations.\ndatasummary_balance: Balance tables with subgroup statistics and difference in means (aka “Table 1”).\ndatasummary_correlation: Correlation tables.\ndatasummary_skim: Quick overview (“skim”) of a dataset.\ndatasummary_df: Turn dataframes into nice tables with titles, notes, etc." + }, + { + "objectID": "index.html#why", + "href": "index.html#why", + "title": "modelsummary: Data and Model Summaries in R", + "section": "Why?", + "text": "Why?\nHere are a few benefits of modelsummary over some alternative packages:\n\nEasy\nmodelsummary is very easy to use. This simple call often suffices:\nlibrary(modelsummary)\n\nmod <- lm(y ~ x, dat)\nThe command above will automatically display a summary table in the Rstudio Viewer or in a web browser. All you need is one word to change the output format. For example, a text-only version of the table can be printed to the Console by typing:\nmodelsummary(mod, output = \"markdown\")\nTables in Microsoft Word and LaTeX formats can be saved to file by typing:\nmodelsummary(mod, output = \"table.docx\")\nmodelsummary(mod, output = \"table.tex\")\n\n\nFlexible\nInformation: The package offers many intuitive and powerful utilities to customize the information reported in a summary table. You can rename, reorder, subset or omit parameter estimates; choose the set of goodness-of-fit statistics to include; display various “robust” standard errors or confidence intervals; add titles, footnotes, or source notes; insert stars or custom characters to indicate levels of statistical significance; or add rows with supplemental information about your models.\nAppearance: Thanks to the tinytable, gt, kableExtra, huxtable, flextable, and DT packages, the appearance of modelsummary tables is endlessly customizable. The appearance customization page shows tables with colored cells, weird text, spanning column labels, row groups, titles, source notes, footnotes, significance stars, and more. This only scratches the surface of possibilities.\nSupported models: Thanks to the broom and parameters, modelsummary supports hundreds of statistical models out-of-the-box. Installing other packages can extend the capabilities further (e.g., broom.mixed). It is also very easy to add or customize your own models.\nOutput formats: modelsummary tables can be saved to HTML, LaTeX, Text/Markdown, Microsoft Word, Powerpoint, RTF, JPG, or PNG formats. They can also be inserted seamlessly in Rmarkdown documents to produce automated documents and reports in PDF, HTML, RTF, or Microsoft Word formats.\n\n\nDangerous\nmodelsummary is dangerous! It allows users to do stupid stuff like inserting squirrels in all your tables.\n\n\n\nReliable\nmodelsummary is reliably dangerous! The package is developed using a suite of unit tests with about 95% coverage, so it (probably) won’t break.\n\n\nCommunity\nmodelsummary does not try to do everything. Instead, it leverages the incredible work of the R community. By building on top of the broom and parameters packages, modelsummary already supports hundreds of model types out-of-the-box. modelsummary also supports five of the most popular table-building and customization packages: gt, kableExtra, huxtable, flextable, and DT packages. By using those packages, modelsummary allows users to produce beautiful, endlessly customizable tables in a wide variety of formats, including HTML, PDF, LaTeX, Markdown, and MS Word.\nOne benefit of this community-focused approach is that when external packages improve, modelsummary improves as well. Another benefit is that leveraging external packages allows modelsummary to have a massively simplified codebase (relative to other similar packages). This should improve long term code maintainability, and allow contributors to participate through GitHub." + }, + { + "objectID": "index.html#how", + "href": "index.html#how", + "title": "modelsummary: Data and Model Summaries in R", + "section": "How?", + "text": "How?\nYou can install modelsummary from CRAN:\ninstall.packages('modelsummary')\nYou can install the development version of modelsummary and its dependencies from R-Universe:\ninstall.packages(\n c(\"modelsummary\", \"tinytable\", \"insight\", \"performance\", \"parameters\"),\n repos = c(\n \"https://vincentarelbundock.r-universe.dev\",\n \"https://easystats.r-universe.dev\"))\nRestart R completely before moving on." + }, + { + "objectID": "index.html#get-started", + "href": "index.html#get-started", + "title": "modelsummary: Data and Model Summaries in R", + "section": "Get started", + "text": "Get started\nThe GET STARTED vignette will walk you through the basics of modelsummary.\nYou will find that there are a million ways to customize the tables and plots produced by modelsummary, but the Get Started page only scratches the surface. For details, see the vignettes:\n\nData Summaries\nModel Summaries\nModel Plots\nmodelsummary extensions and customization\nThemes and Styles" + }, + { + "objectID": "man/fmt_sci.html", + "href": "man/fmt_sci.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding using scientific notation\n\n\n\nfmt_sci(digits = 3, ...)\n\n\n\n\n\n\n\ndigits\n\n\na positive integer indicating how many significant digits are to be used for numeric and complex x.\n\n\n\n\n…\n\n\nadditional arguments passed to format().", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_sci`" + ] + }, + { + "objectID": "man/fmt_sci.html#rounding-using-scientific-notation", + "href": "man/fmt_sci.html#rounding-using-scientific-notation", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding using scientific notation\n\n\n\nfmt_sci(digits = 3, ...)\n\n\n\n\n\n\n\ndigits\n\n\na positive integer indicating how many significant digits are to be used for numeric and complex x.\n\n\n\n\n…\n\n\nadditional arguments passed to format().", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_sci`" + ] + }, + { + "objectID": "man/update_modelsummary.html", + "href": "man/update_modelsummary.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Update modelsummary and its dependencies to the latest R-Universe or CRAN versions. The R session needs to be restarted after install.\n\n\n\nupdate_modelsummary(source = \"development\")\n\n\n\n\n\n\n\nsource\n\n\none of two strings: \"development\" or \"cran\"", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`update_modelsummary`" + ] + }, + { + "objectID": "man/update_modelsummary.html#update-modelsummary-and-its-dependencies", + "href": "man/update_modelsummary.html#update-modelsummary-and-its-dependencies", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Update modelsummary and its dependencies to the latest R-Universe or CRAN versions. The R session needs to be restarted after install.\n\n\n\nupdate_modelsummary(source = \"development\")\n\n\n\n\n\n\n\nsource\n\n\none of two strings: \"development\" or \"cran\"", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`update_modelsummary`" + ] + }, + { + "objectID": "man/coef_rename.html", + "href": "man/coef_rename.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A convenience function which can be passed to the coef_rename argument of the modelsummary function.\n\ncoef_rename(\n x,\n factor = TRUE,\n factor_name = TRUE,\n backticks = TRUE,\n titlecase = TRUE,\n underscore = TRUE,\n asis = TRUE\n)\n\n\n\n\n\nx\n\n\ncharacter vector of term names to transform\n\n\n\n\nfactor\n\n\nboolean remove the \"factor()\" label\n\n\n\n\nfactor_name\n\n\nboolean remove the \"factor()\" label and the name of the variable\n\n\n\n\nbackticks\n\n\nboolean remove backticks\n\n\n\n\ntitlecase\n\n\nboolean convert to title case\n\n\n\n\nunderscore\n\n\nboolean replace underscores by spaces\n\n\n\n\nasis\n\n\nboolean remove the I from as-is formula calls\n\n\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\ndat <- mtcars\ndat$horse_power <- dat$hp\nmod <- lm(mpg ~ horse_power + factor(cyl), dat)\nmodelsummary(mod, coef_rename = coef_rename)\n\n \n\n \n \n\ntinytable_068sp7zsk08y3v08zq4i\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 28.650 \n \n\n \n (1.588)\n \n\nHorse Power\n -0.024 \n \n\n \n (0.015)\n \n\n6 \n -5.968 \n \n\n \n (1.639)\n \n\n8 \n -8.521 \n \n\n \n (2.326)\n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.754 \n \n\nR2 Adj. \n 0.727 \n \n\nAIC \n 169.9 \n \n\nBIC \n 177.2 \n \n\nLog.Lik. \n -79.948\n \n\nF \n 28.585 \n \n\nRMSE \n 2.94", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`coef_rename`" + ] + }, + { + "objectID": "man/coef_rename.html#rename-model-terms", + "href": "man/coef_rename.html#rename-model-terms", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A convenience function which can be passed to the coef_rename argument of the modelsummary function.\n\ncoef_rename(\n x,\n factor = TRUE,\n factor_name = TRUE,\n backticks = TRUE,\n titlecase = TRUE,\n underscore = TRUE,\n asis = TRUE\n)\n\n\n\n\n\nx\n\n\ncharacter vector of term names to transform\n\n\n\n\nfactor\n\n\nboolean remove the \"factor()\" label\n\n\n\n\nfactor_name\n\n\nboolean remove the \"factor()\" label and the name of the variable\n\n\n\n\nbackticks\n\n\nboolean remove backticks\n\n\n\n\ntitlecase\n\n\nboolean convert to title case\n\n\n\n\nunderscore\n\n\nboolean replace underscores by spaces\n\n\n\n\nasis\n\n\nboolean remove the I from as-is formula calls\n\n\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\ndat <- mtcars\ndat$horse_power <- dat$hp\nmod <- lm(mpg ~ horse_power + factor(cyl), dat)\nmodelsummary(mod, coef_rename = coef_rename)\n\n \n\n \n \n\ntinytable_068sp7zsk08y3v08zq4i\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 28.650 \n \n\n \n (1.588)\n \n\nHorse Power\n -0.024 \n \n\n \n (0.015)\n \n\n6 \n -5.968 \n \n\n \n (1.639)\n \n\n8 \n -8.521 \n \n\n \n (2.326)\n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.754 \n \n\nR2 Adj. \n 0.727 \n \n\nAIC \n 169.9 \n \n\nBIC \n 177.2 \n \n\nLog.Lik. \n -79.948\n \n\nF \n 28.585 \n \n\nRMSE \n 2.94", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`coef_rename`" + ] + }, + { + "objectID": "man/fmt_statistic.html", + "href": "man/fmt_statistic.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with decimal digits on a per-statistic basis in the fmt argument for modelsummary()\n\n\n\nfmt_statistic(..., default = 3)\n\n\n\n\n\n\n\n…\n\n\nStatistic names and fmt value\n\n\n\n\ndefault\n\n\nNumber of decimal digits to keep for unspecified terms", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_statistic`" + ] + }, + { + "objectID": "man/fmt_statistic.html#rounding-with-decimal-digits-on-a-per-statistic-basis-in-the-fmt-argument-for-modelsummary", + "href": "man/fmt_statistic.html#rounding-with-decimal-digits-on-a-per-statistic-basis-in-the-fmt-argument-for-modelsummary", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with decimal digits on a per-statistic basis in the fmt argument for modelsummary()\n\n\n\nfmt_statistic(..., default = 3)\n\n\n\n\n\n\n\n…\n\n\nStatistic names and fmt value\n\n\n\n\ndefault\n\n\nNumber of decimal digits to keep for unspecified terms", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_statistic`" + ] + }, + { + "objectID": "man/modelplot.html", + "href": "man/modelplot.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Dot-Whisker plot of coefficient estimates with confidence intervals. For more information, see the Details and Examples sections below, and the vignettes on the modelsummary website: https://modelsummary.com/\n\n\nmodelplot Vignette.\n\n\nmodelplot(\n models,\n conf_level = 0.95,\n coef_map = NULL,\n coef_omit = NULL,\n coef_rename = NULL,\n vcov = NULL,\n exponentiate = FALSE,\n add_rows = NULL,\n facet = FALSE,\n draw = TRUE,\n background = NULL,\n ...\n)\n\n\n\n\n\nmodels\n\n\na model, (named) list of models, or nested list of models.\n\n\nSingle model: modelsummary(model)\n\n\nUnnamed list of models: modelsummary(list(model1, model2))\n\n\nModels are labelled automatically. The default label style can be altered by setting a global option. See below.\n\n\n\n\nNamed list of models: modelsummary(list(“A”=model1, “B”=model2))\n\n\nModels are labelled using the list names.\n\n\n\n\nNested list of models:\n\n\nWhen using the shape argument with \"rbind\", \"rcollapse\", or \"cbind\" values, models can be a nested list of models to display \"panels\" or \"stacks\" of regression models. See the shape argument documentation and examples below.\n\n\n\n\n\n\n\n\nconf_level\n\n\nnumeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models.\n\n\n\n\ncoef_map\n\n\ncharacter vector. Subset, rename, and reorder coefficients. Coefficients omitted from this vector are omitted from the table. The order of the vector determines the order of the table. coef_map can be a named or an unnamed character vector. If coef_map is a named vector, its values define the labels that must appear in the table, and its names identify the original term names stored in the model object: c(“hp:mpg”=“HPxM/G”). See Examples section below.\n\n\n\n\ncoef_omit\n\n\ninteger vector or regular expression to identify which coefficients to omit (or keep) from the table. Positive integers determine which coefficients to omit. Negative integers determine which coefficients to keep. A regular expression can be used to omit coefficients, and perl-compatible \"negative lookaheads\" can be used to specify which coefficients to keep in the table. Examples:\n\n\nc(2, 3, 5): omits the second, third, and fifth coefficients.\n\n\nc(-2, -3, -5): negative values keep the second, third, and fifth coefficients.\n\n\n“ei”: omit coefficients matching the \"ei\" substring.\n\n\n“^Volume$”: omit the \"Volume\" coefficient.\n\n\n“ei|rc”: omit coefficients matching either the \"ei\" or the \"rc\" substrings.\n\n\n“^(?!Vol)”: keep coefficients starting with \"Vol\" (inverse match using a negative lookahead).\n\n\n“^(?!.*ei)“: keep coefficients matching the”ei\" substring.\n\n\n“^(?!.ei|.pt)”: keep coefficients matching either the \"ei\" or the \"pt\" substrings.\n\n\nSee the Examples section below for complete code.\n\n\n\n\n\n\ncoef_rename\n\n\nlogical, named or unnamed character vector, or function\n\n\nLogical: TRUE renames variables based on the \"label\" attribute of each column. See the Example section below.\n\n\nUnnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.\n\n\nNamed character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c(\"hp:mpg\"=\"hp X mpg\")\n\n\nFunction: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)\n\n\n\n\n\n\nvcov\n\n\nrobust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):\n\n\nNULL returns the default uncertainty estimates of the model object\n\n\nstring, vector, or (named) list of strings. \"iid\", \"classical\", and \"constant\" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings \"HC\", \"HC0\", \"HC1\" (alias: \"stata\"), \"HC2\", \"HC3\" (alias: \"robust\"), \"HC4\", \"HC4m\", \"HC5\", \"HAC\", \"NeweyWest\", \"Andrews\", \"panel-corrected\", \"outer-product\", and \"weave\" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. \"BS\", \"bootstrap\", \"residual\", \"mammen\", \"webb\", \"xy\", \"wild\" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (…), but it is safer to define your own custom functions as described in the next bullet.\n\n\nfunction or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).\n\n\nformula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).\n\n\nnamed list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.\n\n\na named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.\n\n\n\n\n\n\nexponentiate\n\n\nTRUE, FALSE, or logical vector of length equal to the number of models. If TRUE, the estimate, conf.low, and conf.high statistics are exponentiated, and the std.error is transformed to exp(estimate)*std.error.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nfacet\n\n\nTRUE or FALSE. When the ‘models’ argument includes several model objects, TRUE draws terms in separate facets, and FALSE draws terms side-by-side (dodged).\n\n\n\n\ndraw\n\n\nTRUE returns a ‘ggplot2’ object, FALSE returns the data.frame used to draw the plot.\n\n\n\n\nbackground\n\n\nA list of ‘ggplot2’ geoms to add to the background of the plot. This is especially useful to display annotations \"behind\" the ‘geom_pointrange’ that ‘modelplot’ draws.\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.\n\n\n\n\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\n# single model\nmod <- lm(hp ~ vs + drat, mtcars)\nmodelplot(mod)\n\n\n\n\n\n\n# omit terms with string matches or regexes\nmodelplot(mod, coef_omit = 'Interc')\n\n\n\n\n\n\n# rename, reorder and subset with 'coef_map'\ncm <- c('vs' = 'V-shape engine',\n 'drat' = 'Rear axle ratio')\nmodelplot(mod, coef_map = cm)\n\n\n\n\n\n\n# several models\nmodels <- list()\nmodels[['Small model']] <- lm(hp ~ vs, mtcars)\nmodels[['Medium model']] <- lm(hp ~ vs + factor(cyl), mtcars)\nmodels[['Large model']] <- lm(hp ~ vs + drat + factor(cyl), mtcars)\nmodelplot(models)\n\n\n\n\n\n\n# add_rows: add an empty reference category\n\nmod <- lm(hp ~ factor(cyl), mtcars)\n\nadd_rows = data.frame(\n term = \"factory(cyl)4\",\n model = \"(1)\",\n estimate = NA)\nattr(add_rows, \"position\") = 3\nmodelplot(mod, add_rows = add_rows)\n\n\n\n\n\n\n# customize your plots with 'ggplot2' functions\nlibrary(ggplot2)\n\nmodelplot(models) +\n scale_color_brewer(type = 'qual') +\n theme_classic()\n\n\n\n\n\n\n# pass arguments to 'geom_pointrange' through the ... ellipsis\nmodelplot(mod, color = 'red', size = 1, fatten = .5)\n\n\n\n\n\n\n# add geoms to the background, behind geom_pointrange\nb <- list(geom_vline(xintercept = 0, color = 'orange'),\n annotate(\"rect\", alpha = .1,\n xmin = -.5, xmax = .5,\n ymin = -Inf, ymax = Inf),\n geom_point(aes(y = term, x = estimate), alpha = .3,\n size = 10, color = 'red', shape = 'square'))\nmodelplot(mod, background = b)\n\n\n\n\n\n\n# logistic regression example\ndf <- as.data.frame(Titanic)\nmod_titanic <- glm(\n Survived ~ Class + Sex,\n family = binomial,\n weight = Freq,\n data = df\n)\n\n# displaying odds ratio using a log scale\nmodelplot(mod_titanic, exponentiate = TRUE) +\n scale_x_log10() +\n xlab(\"Odds Ratios and 95% confidence intervals\")", + "crumbs": [ + "Get started", + "Functions", + "`modelplot`" + ] + }, + { + "objectID": "man/modelplot.html#model-summary-plots-with-estimates-and-confidence-intervals", + "href": "man/modelplot.html#model-summary-plots-with-estimates-and-confidence-intervals", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Dot-Whisker plot of coefficient estimates with confidence intervals. For more information, see the Details and Examples sections below, and the vignettes on the modelsummary website: https://modelsummary.com/\n\n\nmodelplot Vignette.\n\n\nmodelplot(\n models,\n conf_level = 0.95,\n coef_map = NULL,\n coef_omit = NULL,\n coef_rename = NULL,\n vcov = NULL,\n exponentiate = FALSE,\n add_rows = NULL,\n facet = FALSE,\n draw = TRUE,\n background = NULL,\n ...\n)\n\n\n\n\n\nmodels\n\n\na model, (named) list of models, or nested list of models.\n\n\nSingle model: modelsummary(model)\n\n\nUnnamed list of models: modelsummary(list(model1, model2))\n\n\nModels are labelled automatically. The default label style can be altered by setting a global option. See below.\n\n\n\n\nNamed list of models: modelsummary(list(“A”=model1, “B”=model2))\n\n\nModels are labelled using the list names.\n\n\n\n\nNested list of models:\n\n\nWhen using the shape argument with \"rbind\", \"rcollapse\", or \"cbind\" values, models can be a nested list of models to display \"panels\" or \"stacks\" of regression models. See the shape argument documentation and examples below.\n\n\n\n\n\n\n\n\nconf_level\n\n\nnumeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models.\n\n\n\n\ncoef_map\n\n\ncharacter vector. Subset, rename, and reorder coefficients. Coefficients omitted from this vector are omitted from the table. The order of the vector determines the order of the table. coef_map can be a named or an unnamed character vector. If coef_map is a named vector, its values define the labels that must appear in the table, and its names identify the original term names stored in the model object: c(“hp:mpg”=“HPxM/G”). See Examples section below.\n\n\n\n\ncoef_omit\n\n\ninteger vector or regular expression to identify which coefficients to omit (or keep) from the table. Positive integers determine which coefficients to omit. Negative integers determine which coefficients to keep. A regular expression can be used to omit coefficients, and perl-compatible \"negative lookaheads\" can be used to specify which coefficients to keep in the table. Examples:\n\n\nc(2, 3, 5): omits the second, third, and fifth coefficients.\n\n\nc(-2, -3, -5): negative values keep the second, third, and fifth coefficients.\n\n\n“ei”: omit coefficients matching the \"ei\" substring.\n\n\n“^Volume$”: omit the \"Volume\" coefficient.\n\n\n“ei|rc”: omit coefficients matching either the \"ei\" or the \"rc\" substrings.\n\n\n“^(?!Vol)”: keep coefficients starting with \"Vol\" (inverse match using a negative lookahead).\n\n\n“^(?!.*ei)“: keep coefficients matching the”ei\" substring.\n\n\n“^(?!.ei|.pt)”: keep coefficients matching either the \"ei\" or the \"pt\" substrings.\n\n\nSee the Examples section below for complete code.\n\n\n\n\n\n\ncoef_rename\n\n\nlogical, named or unnamed character vector, or function\n\n\nLogical: TRUE renames variables based on the \"label\" attribute of each column. See the Example section below.\n\n\nUnnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.\n\n\nNamed character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c(\"hp:mpg\"=\"hp X mpg\")\n\n\nFunction: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)\n\n\n\n\n\n\nvcov\n\n\nrobust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):\n\n\nNULL returns the default uncertainty estimates of the model object\n\n\nstring, vector, or (named) list of strings. \"iid\", \"classical\", and \"constant\" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings \"HC\", \"HC0\", \"HC1\" (alias: \"stata\"), \"HC2\", \"HC3\" (alias: \"robust\"), \"HC4\", \"HC4m\", \"HC5\", \"HAC\", \"NeweyWest\", \"Andrews\", \"panel-corrected\", \"outer-product\", and \"weave\" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. \"BS\", \"bootstrap\", \"residual\", \"mammen\", \"webb\", \"xy\", \"wild\" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (…), but it is safer to define your own custom functions as described in the next bullet.\n\n\nfunction or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).\n\n\nformula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).\n\n\nnamed list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.\n\n\na named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.\n\n\n\n\n\n\nexponentiate\n\n\nTRUE, FALSE, or logical vector of length equal to the number of models. If TRUE, the estimate, conf.low, and conf.high statistics are exponentiated, and the std.error is transformed to exp(estimate)*std.error.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nfacet\n\n\nTRUE or FALSE. When the ‘models’ argument includes several model objects, TRUE draws terms in separate facets, and FALSE draws terms side-by-side (dodged).\n\n\n\n\ndraw\n\n\nTRUE returns a ‘ggplot2’ object, FALSE returns the data.frame used to draw the plot.\n\n\n\n\nbackground\n\n\nA list of ‘ggplot2’ geoms to add to the background of the plot. This is especially useful to display annotations \"behind\" the ‘geom_pointrange’ that ‘modelplot’ draws.\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.\n\n\n\n\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\n# single model\nmod <- lm(hp ~ vs + drat, mtcars)\nmodelplot(mod)\n\n\n\n\n\n\n# omit terms with string matches or regexes\nmodelplot(mod, coef_omit = 'Interc')\n\n\n\n\n\n\n# rename, reorder and subset with 'coef_map'\ncm <- c('vs' = 'V-shape engine',\n 'drat' = 'Rear axle ratio')\nmodelplot(mod, coef_map = cm)\n\n\n\n\n\n\n# several models\nmodels <- list()\nmodels[['Small model']] <- lm(hp ~ vs, mtcars)\nmodels[['Medium model']] <- lm(hp ~ vs + factor(cyl), mtcars)\nmodels[['Large model']] <- lm(hp ~ vs + drat + factor(cyl), mtcars)\nmodelplot(models)\n\n\n\n\n\n\n# add_rows: add an empty reference category\n\nmod <- lm(hp ~ factor(cyl), mtcars)\n\nadd_rows = data.frame(\n term = \"factory(cyl)4\",\n model = \"(1)\",\n estimate = NA)\nattr(add_rows, \"position\") = 3\nmodelplot(mod, add_rows = add_rows)\n\n\n\n\n\n\n# customize your plots with 'ggplot2' functions\nlibrary(ggplot2)\n\nmodelplot(models) +\n scale_color_brewer(type = 'qual') +\n theme_classic()\n\n\n\n\n\n\n# pass arguments to 'geom_pointrange' through the ... ellipsis\nmodelplot(mod, color = 'red', size = 1, fatten = .5)\n\n\n\n\n\n\n# add geoms to the background, behind geom_pointrange\nb <- list(geom_vline(xintercept = 0, color = 'orange'),\n annotate(\"rect\", alpha = .1,\n xmin = -.5, xmax = .5,\n ymin = -Inf, ymax = Inf),\n geom_point(aes(y = term, x = estimate), alpha = .3,\n size = 10, color = 'red', shape = 'square'))\nmodelplot(mod, background = b)\n\n\n\n\n\n\n# logistic regression example\ndf <- as.data.frame(Titanic)\nmod_titanic <- glm(\n Survived ~ Class + Sex,\n family = binomial,\n weight = Freq,\n data = df\n)\n\n# displaying odds ratio using a log scale\nmodelplot(mod_titanic, exponentiate = TRUE) +\n scale_x_log10() +\n xlab(\"Odds Ratios and 95% confidence intervals\")", + "crumbs": [ + "Get started", + "Functions", + "`modelplot`" + ] + }, + { + "objectID": "man/fmt_term.html", + "href": "man/fmt_term.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with decimal digits on a per-term basis in the fmt argument for modelsummary()\n\n\n\nfmt_term(..., default = 3)\n\n\n\n\n\n\n\n…\n\n\nTerm names and fmt value\n\n\n\n\ndefault\n\n\nNumber of decimal digits to keep for unspecified terms", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_term`" + ] + }, + { + "objectID": "man/fmt_term.html#rounding-with-decimal-digits-on-a-per-term-basis-in-the-fmt-argument-for-modelsummary", + "href": "man/fmt_term.html#rounding-with-decimal-digits-on-a-per-term-basis-in-the-fmt-argument-for-modelsummary", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with decimal digits on a per-term basis in the fmt argument for modelsummary()\n\n\n\nfmt_term(..., default = 3)\n\n\n\n\n\n\n\n…\n\n\nTerm names and fmt value\n\n\n\n\ndefault\n\n\nNumber of decimal digits to keep for unspecified terms", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_term`" + ] + }, + { + "objectID": "man/fmt_significant.html", + "href": "man/fmt_significant.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "The number of decimal digits to keep after the decimal is assessed\n\n\n\nfmt_significant(digits = 3, ...)\n\n\n\n\n\n\n\ndigits\n\n\nNumber of significant digits to keep.\n\n\n\n\n…\n\n\nAdditional arguments are passed to the format() function (e.g., big.marks, scientific). See ?format", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_significant`" + ] + }, + { + "objectID": "man/fmt_significant.html#rounding-with-significant-digits-in-the-fmt-argument", + "href": "man/fmt_significant.html#rounding-with-significant-digits-in-the-fmt-argument", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "The number of decimal digits to keep after the decimal is assessed\n\n\n\nfmt_significant(digits = 3, ...)\n\n\n\n\n\n\n\ndigits\n\n\nNumber of significant digits to keep.\n\n\n\n\n…\n\n\nAdditional arguments are passed to the format() function (e.g., big.marks, scientific). See ?format", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_significant`" + ] + }, + { + "objectID": "man/gof_map.html", + "href": "man/gof_map.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "By default, this data frame is passed to the ‘gof_map’ argument of the ‘modelsummary’ function. Users can modify this data frame to customize the list of statistics to display and their format. See example below.\n\ngof_map\n\n\ndata.frame with 4 columns of character data: raw, clean, fmt, omit\n\n\nlibrary(modelsummary)\n\nif (identical(Sys.getenv(\"pkgdown\"), \"true\")) {\n\nlibrary(modelsummary)\nmod <- lm(wt ~ drat, data = mtcars)\ngm <- modelsummary::gof_map\ngm$omit[gm$raw == 'deviance'] <- FALSE\ngm$fmt[gm$raw == 'r.squared'] <- \"%.5f\"\nmodelsummary(mod, gof_map = gm)\n}", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`gof_map`" + ] + }, + { + "objectID": "man/gof_map.html#data.frame-used-to-clean-up-and-format-goodness-of-fit-statistics", + "href": "man/gof_map.html#data.frame-used-to-clean-up-and-format-goodness-of-fit-statistics", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "By default, this data frame is passed to the ‘gof_map’ argument of the ‘modelsummary’ function. Users can modify this data frame to customize the list of statistics to display and their format. See example below.\n\ngof_map\n\n\ndata.frame with 4 columns of character data: raw, clean, fmt, omit\n\n\nlibrary(modelsummary)\n\nif (identical(Sys.getenv(\"pkgdown\"), \"true\")) {\n\nlibrary(modelsummary)\nmod <- lm(wt ~ drat, data = mtcars)\ngm <- modelsummary::gof_map\ngm$omit[gm$raw == 'deviance'] <- FALSE\ngm$fmt[gm$raw == 'r.squared'] <- \"%.5f\"\nmodelsummary(mod, gof_map = gm)\n}", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`gof_map`" + ] + }, + { + "objectID": "man/fmt_decimal.html", + "href": "man/fmt_decimal.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with decimal digits in the fmt argument\n\n\n\nfmt_decimal(digits = 3, pdigits = NULL, ...)\n\n\n\n\n\n\n\ndigits\n\n\nNumber of decimal digits to keep, including trailing zeros.\n\n\n\n\npdigits\n\n\nNumber of decimal digits to keep for p values. If NULL, the value of digits is used.\n\n\n\n\n…\n\n\nAdditional arguments are passed to the format() function (e.g., big.marks, scientific). See ?format", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_decimal`" + ] + }, + { + "objectID": "man/fmt_decimal.html#rounding-with-decimal-digits-in-the-fmt-argument", + "href": "man/fmt_decimal.html#rounding-with-decimal-digits-in-the-fmt-argument", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with decimal digits in the fmt argument\n\n\n\nfmt_decimal(digits = 3, pdigits = NULL, ...)\n\n\n\n\n\n\n\ndigits\n\n\nNumber of decimal digits to keep, including trailing zeros.\n\n\n\n\npdigits\n\n\nNumber of decimal digits to keep for p values. If NULL, the value of digits is used.\n\n\n\n\n…\n\n\nAdditional arguments are passed to the format() function (e.g., big.marks, scientific). See ?format", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_decimal`" + ] + }, + { + "objectID": "man/modelsummary.html", + "href": "man/modelsummary.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Create beautiful and customizable tables to summarize several statistical models side-by-side. This function supports dozens of statistical models, and it can produce tables in HTML, LaTeX, Word, Markdown, Typst, PDF, PowerPoint, Excel, RTF, JPG, or PNG. The appearance of the tables can be customized extensively by specifying the output argument, and by using functions from one of the supported table customization packages: tinytable, kableExtra, gt, flextable, huxtable, DT. For more information, see the Details and Examples sections below, and the vignettes on the modelsummary website: https://modelsummary.com/\n\n\nThe modelsummary Vignette includes dozens of examples of tables with extensive customizations.\n\n\nThe Appearance Vignette shows how to modify the look of tables.\n\n\nmodelsummary(\n models,\n output = \"default\",\n fmt = 3,\n estimate = \"estimate\",\n statistic = \"std.error\",\n vcov = NULL,\n conf_level = 0.95,\n exponentiate = FALSE,\n stars = FALSE,\n shape = term + statistic ~ model,\n coef_map = NULL,\n coef_omit = NULL,\n coef_rename = FALSE,\n gof_map = NULL,\n gof_omit = NULL,\n gof_function = NULL,\n group_map = NULL,\n add_columns = NULL,\n add_rows = NULL,\n align = NULL,\n notes = NULL,\n title = NULL,\n escape = TRUE,\n ...\n)\n\n\n\n\n\nmodels\n\n\na model, (named) list of models, or nested list of models.\n\n\nSingle model: modelsummary(model)\n\n\nUnnamed list of models: modelsummary(list(model1, model2))\n\n\nModels are labelled automatically. The default label style can be altered by setting a global option. See below.\n\n\n\n\nNamed list of models: modelsummary(list(“A”=model1, “B”=model2))\n\n\nModels are labelled using the list names.\n\n\n\n\nNested list of models:\n\n\nWhen using the shape argument with \"rbind\", \"rcollapse\", or \"cbind\" values, models can be a nested list of models to display \"panels\" or \"stacks\" of regression models. See the shape argument documentation and examples below.\n\n\n\n\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_decimal(digits = 2, pdigits = 3): Decimal digits for estimate and p values\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_term(“(Intercept)” = 1, “X” = 2): Format terms differently\n\n\nfmt = fmt_statistic(“estimate” = 1, “r.squared” = 6): Format statistics differently.\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\nstring:\n\n\nNote on LaTeX output: To ensure proper typography, all numeric entries are enclosed in the command, which requires the siunitx package to be loaded in the LaTeX preamble. This behavior can be altered with global options. See the ‘Details’ section.\n\n\n\n\n\n\nestimate\n\n\na single string or a character vector of length equal to the number of models. Valid entries include any column name of the data.frame produced by get_estimates(model), and strings with curly braces compatible with the glue package format. Examples:\n\n\n“estimate”\n\n\n“{estimate} ({std.error}){stars}”\n\n\n“{estimate} [{conf.low}, {conf.high}]”\n\n\n\n\n\n\nstatistic\n\n\nvector of strings or glue strings which select uncertainty statistics to report vertically below the estimate. NULL omits all uncertainty statistics.\n\n\n\"conf.int\", \"std.error\", \"statistic\", \"p.value\", \"conf.low\", \"conf.high\", or any column name produced by get_estimates(model)\n\n\nglue package strings with braces, with or without R functions, such as:\n\n\n“{p.value} [{conf.low}, {conf.high}]”\n\n\n“Std.Error: {std.error}”\n\n\n“{exp(estimate) * std.error}”\n\n\nNumbers are automatically rounded and converted to strings. To apply functions to their numeric values, as in the last glue example, users must set fmt=NULL.\n\n\nParentheses are added automatically unless the string includes glue curly braces {}.\n\n\n\n\nNotes:\n\n\nThe names of the statistic are used a column names when using the shape argument to display statistics as columns:\n\n\nstatistic=c(“p”=“p.value”, “[”=”conf.low”, ”]”=“conf.high”)\n\n\n\n\nSome statistics are not supported for all models. See column names in get_estimates(model), and visit the website to learn how to add custom statistics.\n\n\n\n\n\n\n\n\nvcov\n\n\nrobust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):\n\n\nNULL returns the default uncertainty estimates of the model object\n\n\nstring, vector, or (named) list of strings. \"iid\", \"classical\", and \"constant\" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings \"HC\", \"HC0\", \"HC1\" (alias: \"stata\"), \"HC2\", \"HC3\" (alias: \"robust\"), \"HC4\", \"HC4m\", \"HC5\", \"HAC\", \"NeweyWest\", \"Andrews\", \"panel-corrected\", \"outer-product\", and \"weave\" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. \"BS\", \"bootstrap\", \"residual\", \"mammen\", \"webb\", \"xy\", \"wild\" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (…), but it is safer to define your own custom functions as described in the next bullet.\n\n\nfunction or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).\n\n\nformula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).\n\n\nnamed list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.\n\n\na named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.\n\n\n\n\n\n\nconf_level\n\n\nnumeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models.\n\n\n\n\nexponentiate\n\n\nTRUE, FALSE, or logical vector of length equal to the number of models. If TRUE, the estimate, conf.low, and conf.high statistics are exponentiated, and the std.error is transformed to exp(estimate)*std.error.\n\n\n\n\nstars\n\n\nto indicate statistical significance\n\n\nFALSE (default): no significance stars.\n\n\nTRUE: +=.1, =.05, =.01, =0.001\n\n\nNamed numeric vector for custom stars such as c(’*’ = .1, ‘+’ = .05)\n\n\nNote: a legend will not be inserted at the bottom of the table when the estimate or statistic arguments use \"glue strings\" with stars.\n\n\n\n\n\n\nshape\n\n\nNULL, formula, or string which determines the shape of a table.\n\n\nNULL: Default shape with terms in rows and models in columns.\n\n\nFormula: The left side determines what appears on rows, and the right side determines what appears on columns. The formula can include one or more group identifier(s) to display related terms together, which can be useful for models with multivariate outcomes or grouped coefficients (See examples section below). The group identifier(s) must be column names produced by: get_estimates(model). The group identifier(s) can be combined with the term identifier in a single column by using the colon to represent an interaction. If an incomplete formula is supplied (e.g., ~statistic), modelsummary tries to complete it automatically. Goodness-of-fit statistics are only appended to the bottom of the table when model is on the right hand side of the formula (i.e., columns). Potential shape values include:\n\n\nterm + statistic ~ model: default\n\n\nterm ~ model + statistic: statistics in separate columns\n\n\nmodel + statistic ~ term: models in rows and terms in columns\n\n\nterm + response + statistic ~ model: term and group id in separate columns\n\n\nterm : response + statistic ~ model: term and group id in a single column\n\n\nterm ~ response\n\n\n\n\nString: \"cbind\", \"rbind\", \"rcollapse\"\n\n\n\"cbind\": side-by-side models with autmoatic spanning column headers to group models (tinytable only feature).\n\n\n\"rbind\" or \"rcollapse\": \"panels\" or \"stacks\" of regression models.\n\n\nthe models argument must be a (potentially named) nested list of models.\n\n\n\n\nUnnamed nested list with 2 panels: list(list(model1, model2), list(model3, model4))\n\n\nNamed nested list with 2 panels: list(“Panel A” = list(model1, model2), “Panel B” = list(model3, model4))\n\n\nNamed panels and named models: list(“Panel A” = list(“(I)” = model1, “(II)” = model2), “Panel B” = list(“(I)” = model3, “(II)” = model4))\n\n\n\n\n\"rbind\": Bind the rows of independent regression tables\n\n\n\"rcollapse\": Bind the rows of regression tables and create a panel at the bottom where we \"collapse\" goodness-of-fit statistics which are identical across models.\n\n\n\n\n\n\n\n\ncoef_map\n\n\ncharacter vector. Subset, rename, and reorder coefficients. Coefficients omitted from this vector are omitted from the table. The order of the vector determines the order of the table. coef_map can be a named or an unnamed character vector. If coef_map is a named vector, its values define the labels that must appear in the table, and its names identify the original term names stored in the model object: c(“hp:mpg”=“HPxM/G”). See Examples section below.\n\n\n\n\ncoef_omit\n\n\ninteger vector or regular expression to identify which coefficients to omit (or keep) from the table. Positive integers determine which coefficients to omit. Negative integers determine which coefficients to keep. A regular expression can be used to omit coefficients, and perl-compatible \"negative lookaheads\" can be used to specify which coefficients to keep in the table. Examples:\n\n\nc(2, 3, 5): omits the second, third, and fifth coefficients.\n\n\nc(-2, -3, -5): negative values keep the second, third, and fifth coefficients.\n\n\n“ei”: omit coefficients matching the \"ei\" substring.\n\n\n“^Volume$”: omit the \"Volume\" coefficient.\n\n\n“ei|rc”: omit coefficients matching either the \"ei\" or the \"rc\" substrings.\n\n\n“^(?!Vol)”: keep coefficients starting with \"Vol\" (inverse match using a negative lookahead).\n\n\n“^(?!.*ei)“: keep coefficients matching the”ei\" substring.\n\n\n“^(?!.ei|.pt)”: keep coefficients matching either the \"ei\" or the \"pt\" substrings.\n\n\nSee the Examples section below for complete code.\n\n\n\n\n\n\ncoef_rename\n\n\nlogical, named or unnamed character vector, or function\n\n\nLogical: TRUE renames variables based on the \"label\" attribute of each column. See the Example section below.\n\n\nUnnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.\n\n\nNamed character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c(\"hp:mpg\"=\"hp X mpg\")\n\n\nFunction: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)\n\n\n\n\n\n\ngof_map\n\n\nrename, reorder, and omit goodness-of-fit statistics and other model information. This argument accepts 4 types of values:\n\n\nNULL (default): the modelsummary::gof_map dictionary is used for formatting, and all unknown statistic are included.\n\n\ncharacter vector: \"all\", \"none\", or a vector of statistics such as c(“rmse”, “nobs”, “r.squared”). Elements correspond to colnames in the data.frame produced by get_gof(model). The modelsummary::gof_map default dictionary is used to format and rename statistics.\n\n\nNA: excludes all statistics from the bottom part of the table.\n\n\ndata.frame with 3 columns named \"raw\", \"clean\", \"fmt\". Unknown statistics are omitted. See the ‘Examples’ section below. The fmt column in this data frame only accepts integers. For more flexibility, use a list of lists, as described in the next bullet.\n\n\nlist of lists, each of which includes 3 elements named \"raw\", \"clean\", \"fmt\". Unknown statistics are omitted. See the ‘Examples section below’.\n\n\n\n\n\n\ngof_omit\n\n\nstring regular expression (perl-compatible) used to determine which statistics to omit from the bottom section of the table. A \"negative lookahead\" can be used to specify which statistics to keep in the table. Examples:\n\n\n“IC”: omit statistics matching the \"IC\" substring.\n\n\n“BIC|AIC”: omit statistics matching the \"AIC\" or \"BIC\" substrings.\n\n\n“^(?!.*IC)“: keep statistics matching the”IC\" substring.\n\n\n\n\n\n\ngof_function\n\n\nfunction which accepts a model object in the model argument and returns a 1-row data.frame with one custom goodness-of-fit statistic per column.\n\n\n\n\ngroup_map\n\n\nnamed or unnamed character vector. Subset, rename, and reorder coefficient groups specified a grouping variable specified in the shape argument formula. This argument behaves like coef_map.\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as #’ your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the columns positions. See Examples section below.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.\n\n\n\n\n\n\nThe modelsummary_list output is a lightweight format which can be used to save model results, so they can be fed back to modelsummary later to avoid extracting results again.\nWhen a file name with a valid extension is supplied to the output argument, the table is written immediately to file. If you want to customize your table by post-processing it with an external package, you need to choose a different output format and saving mechanism. Unfortunately, the approach differs from package to package:\n\n\ntinytable: set output=“tinytable”, post-process your table, and use the tinytable::save_tt function.\n\n\ngt: set output=“gt”, post-process your table, and use the gt::gtsave function.\n\n\nkableExtra: set output to your destination format (e.g., \"latex\", \"html\", \"markdown\"), post-process your table, and use kableExtra::save_kable function.\n\n\n\nTo use a string such as \"robust\" or \"HC0\", your model must be supported by the sandwich package. This includes objects such as: lm, glm, survreg, coxph, mlogit, polr, hurdle, zeroinfl, and more.\nNULL, \"classical\", \"iid\", and \"constant\" are aliases which do not modify uncertainty estimates and simply report the default standard errors stored in the model object.\nOne-sided formulas such as ~clusterid are passed to the sandwich::vcovCL function.\nMatrices and functions producing variance-covariance matrices are first passed to lmtest. If this does not work, modelsummary attempts to take the square root of the diagonal to adjust \"std.error\", but the other uncertainty estimates are not be adjusted.\nNumeric vectors are formatted according to fmt and placed in brackets. Character vectors printed as given, without parentheses.\nIf your model type is supported by the lmtest package, the vcov argument will try to use that package to adjust all the uncertainty estimates, including \"std.error\", \"statistic\", \"p.value\", and \"conf.int\". If your model is not supported by lmtest, only the \"std.error\" will be adjusted by, for example, taking the square root of the matrix’s diagonal.\n\na regression table in a format determined by the output argument.\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\nIt can take a long time to compute and extract summary statistics from certain models (e.g., Bayesian). In those cases, users can parallelize the process. Since parallelization occurs at the model level, no speedup is available for tables with a single model. Users on mac or linux can launch parallel computation using the built-in parallel package. All they need to do is supply a mc.cores argument which will be pushed forward to the parallel::mclapply function:\n\nmodelsummary(model_list, mc.cores = 5)\n\n\nAll users can also use the future.apply package to parallelize model summaries. For example, to use 4 cores to extract results:\n\nlibrary(future.apply)\nplan(multicore, workers = 4)\noptions(\"modelsummary_future\" = TRUE)\nmodelsummary(model_list)\n\n\nNote that the \"multicore\" plan only parallelizes under mac or linux. Windows users can use plan(multisession) instead. However, note that the first time modelsummary() is called under multisession can be a fair bit longer, because of extra costs in passing data to and loading required packages on to workers. Subsequent calls to modelsummary() will often be much faster.\nSome users have reported difficult to reproduce errors when using the future package with some packages. The future parallelization in modelsummary can be disabled by calling:\noptions(“modelsummary_future” = FALSE)\n\nArel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’\n\n\nlibrary(modelsummary)\n\n\n# The `modelsummary` website includes \\emph{many} examples and tutorials:\n# https://modelsummary.com\n\nlibrary(modelsummary)\n\n# load data and estimate models\nutils::data(trees)\nmodels <- list()\nmodels[['Bivariate']] <- lm(Girth ~ Height, data = trees)\nmodels[['Multivariate']] <- lm(Girth ~ Height + Volume, data = trees)\n\n# simple table\nmodelsummary(models)\n\n \n\n \n \n\ntinytable_mcj4zhgw5up1bpuiazvv\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# statistic\nmodelsummary(models, statistic = NULL)\n\n \n\n \n \n\ntinytable_qrrm1ns1xhp54009wgtz\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\nHeight \n 0.256 \n -0.045 \n \n\nVolume \n \n 0.195 \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = 'p.value')\n\n \n\n \n \n\ntinytable_he4qy7ao5dkgshldjxv8\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (0.308)\n (\n \n\n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.003)\n (0.119) \n \n\nVolume \n \n 0.195 \n \n\n \n \n (\n \n\n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = 'statistic')\n\n \n\n \n \n\ntinytable_jv2mi0vsnbljzcxn55oe\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (-1.038)\n (5.482) \n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (3.272) \n (-1.609)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (17.816)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = 'conf.int', conf_level = 0.99)\n\n \n\n \n \n\ntinytable_qhae4g99mpkj94vw8zz2\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n [-22.617, 10.240]\n [5.364, 16.269]\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n [0.040, 0.471] \n [-0.124, 0.033]\n \n\nVolume \n \n 0.195 \n \n\n \n \n [0.165, 0.225] \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = c(\"t = {statistic}\",\n \"se = {std.error}\",\n \"conf.int\"))\n\n \n\n \n \n\ntinytable_bd2w1unh5si2ob1nwap9\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n t = -1.038 \n t = 5.482 \n \n\n \n se = 5.960 \n se = 1.973 \n \n\n \n [-18.378, 6.002]\n [6.774, 14.858]\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n t = 3.272 \n t = -1.609 \n \n\n \n se = 0.078 \n se = 0.028 \n \n\n \n [0.096, 0.416] \n [-0.103, 0.012]\n \n\nVolume \n \n 0.195 \n \n\n \n \n t = 17.816 \n \n\n \n \n se = 0.011 \n \n\n \n \n [0.173, 0.218] \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# estimate\nmodelsummary(models,\n statistic = NULL,\n estimate = \"{estimate} [{conf.low}, {conf.high}]\")\n\n \n\n \n \n\ntinytable_idwa3y8zpe8oumq9dmbj\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 [-18.378, 6.002]\n 10.816 [6.774, 14.858]\n \n\nHeight \n 0.256 [0.096, 0.416] \n -0.045 [-0.103, 0.012]\n \n\nVolume \n \n 0.195 [0.173, 0.218] \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models,\n estimate = c(\"{estimate}{stars}\",\n \"{estimate} ({std.error})\"))\n\n \n\n \n \n\ntinytable_pkh9uv1j7tevhruib11c\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 (1.973)\n \n\n \n (5.960)\n (1.973) \n \n\nHeight \n 0.256**\n -0.045 (0.028)\n \n\n \n (0.078)\n (0.028) \n \n\nVolume \n \n 0.195 (0.011) \n \n\n \n \n (0.011) \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# vcov\nmodelsummary(models, vcov = \"robust\")\n\n \n\n \n \n\ntinytable_dohd2tu9jincrqw9navw\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (6.717)\n (2.544)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.090)\n (0.035)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.014)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 8.021 \n 100.427\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n HC3 \n HC3 \n \n\n\n\n\n \n\nmodelsummary(models, vcov = list(\"classical\", \"stata\"))\n\n \n\n \n \n\ntinytable_h4yy74l84znfd2ulobjw\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (2.261)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.031)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.012)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 151.435\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n IID \n HC1 \n \n\n\n\n\n \n\nmodelsummary(models, vcov = sandwich::vcovHC)\n\n \n\n \n \n\ntinytable_x9abw2if38t63xnw5z4c\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (6.717)\n (2.544)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.090)\n (0.035)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.014)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Custom \n Custom \n \n\n\n\n\n \n\nmodelsummary(models,\n vcov = list(stats::vcov, sandwich::vcovHC))\n\n \n\n \n \n\ntinytable_zx024ku0vvosj0cx9h3e\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (2.544)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.035)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.014)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Custom \n Custom \n \n\n\n\n\n \n\nmodelsummary(models,\n vcov = list(c(\"(Intercept)\"=\"\", \"Height\"=\"!\"),\n c(\"(Intercept)\"=\"\", \"Height\"=\"!\", \"Volume\"=\"!!\")))\n\n \n\n \n \n\ntinytable_gs5awfdrsxdfx7mp2ve7\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n ! \n ! \n \n\nVolume \n \n 0.195 \n \n\n \n \n !! \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Custom \n Custom \n \n\n\n\n\n \n\n# vcov with custom names\nmodelsummary(\n models,\n vcov = list(\"Stata Corp\" = \"stata\",\n \"Newey Lewis & the News\" = \"NeweyWest\"))\n\n \n\n \n \n\ntinytable_60fu490ojr1t5pblfiij\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (6.171) \n (1.839) \n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.083) \n (0.022) \n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.007) \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Stata Corp\n Newey Lewis & the News\n \n\n\n\n\n \n\n# fmt\nmod <- lm(mpg ~ hp + drat + qsec, data = mtcars)\n\nmodelsummary(mod, fmt = 3)\n\n \n\n \n \n\ntinytable_x3h0ityo4f865lgcnncl\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.737 \n \n\n \n (13.020)\n \n\nhp \n -0.058 \n \n\n \n (0.014) \n \n\ndrat \n 4.429 \n \n\n \n (1.292) \n \n\nqsec \n -0.284 \n \n\n \n (0.489) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_significant(3))\n\n \n\n \n \n\ntinytable_j6f4s5owmade787l5bsb\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7 \n \n\n \n (13.0) \n \n\nhp \n -0.0580 \n \n\n \n (0.0142)\n \n\ndrat \n 4.43 \n \n\n \n (1.29) \n \n\nqsec \n -0.284 \n \n\n \n (0.489) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = NULL)\n\n \n\n \n \n\ntinytable_f0exllns2gcztktcjygr\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7366200480466 \n \n\n \n (13.0197907534221) \n \n\nhp \n -0.057972987581075 \n \n\n \n (0.014208609097443)\n \n\ndrat \n 4.42875344653986 \n \n\n \n (1.29169225236228) \n \n\nqsec \n -0.284074290906574 \n \n\n \n (0.489229280152) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_decimal(4))\n\n \n\n \n \n\ntinytable_9uvqs6k8qkl5zmtdi5cr\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7366 \n \n\n \n (13.0198)\n \n\nhp \n -0.0580 \n \n\n \n (0.0142) \n \n\ndrat \n 4.4288 \n \n\n \n (1.2917) \n \n\nqsec \n -0.2841 \n \n\n \n (0.4892) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_sprintf(\"%.5f\"))\n\n \n\n \n \n\ntinytable_skia0w0qpih8cryrs5x7\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.73662 \n \n\n \n (13.01979)\n \n\nhp \n -0.05797 \n \n\n \n (0.01421) \n \n\ndrat \n 4.42875 \n \n\n \n (1.29169) \n \n\nqsec \n -0.28407 \n \n\n \n (0.48923) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_statistic(estimate = 4, conf.int = 1), statistic = \"conf.int\")\n\n \n\n \n \n\ntinytable_ye03yw1s7yjnv916nfq1\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7366 \n \n\n \n [-8.9, 44.4]\n \n\nhp \n -0.0580 \n \n\n \n [-0.1, 0.0] \n \n\ndrat \n 4.4288 \n \n\n \n [1.8, 7.1] \n \n\nqsec \n -0.2841 \n \n\n \n [-1.3, 0.7] \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_term(hp = 4, drat = 1, default = 2))\n\n \n\n \n \n\ntinytable_f3jackzt6fgrtnoisuf6\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.74 \n \n\n \n (13.02) \n \n\nhp \n -0.0580 \n \n\n \n (0.0142)\n \n\ndrat \n 4.4 \n \n\n \n (1.3) \n \n\nqsec \n -0.28 \n \n\n \n (0.49) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nm <- lm(mpg ~ I(hp * 1000) + drat, data = mtcars)\nf <- function(x) format(x, digits = 3, nsmall = 2, scientific = FALSE, trim = TRUE)\nmodelsummary(m, fmt = f, gof_map = NA)\n\n \n\n \n \n\ntinytable_2w2n9juxyb78dfqqqc09\n\n\n \n\n \n (1)\n \n\n\n(Intercept) \n 10.7898612 \n \n\n \n (5.07775160)\n \n\nI(hp * 1000)\n -0.0000518 \n \n\n \n (0.00000929)\n \n\ndrat \n 4.6981578 \n \n\n \n (1.19163348)\n \n\n\n\n\n \n\n# coef_rename\nmodelsummary(models, coef_rename = c('Volume' = 'Large', 'Height' = 'Tall'))\n\n \n\n \n \n\ntinytable_4pwqwj6b87mwuxkuka2v\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nTall \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nLarge \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, coef_rename = toupper)\n\n \n\n \n \n\ntinytable_368s8x0z4lodkykk2jsj\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(INTERCEPT)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHEIGHT \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVOLUME \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, coef_rename = coef_rename)\n\n \n\n \n \n\ntinytable_36nrj7aeah44jz3si96q\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# coef_rename = TRUE for variable labels\ndatlab <- mtcars\ndatlab$cyl <- factor(datlab$cyl)\nattr(datlab$hp, \"label\") <- \"Horsepower\"\nattr(datlab$cyl, \"label\") <- \"Cylinders\"\nmodlab <- lm(mpg ~ hp * drat + cyl, data = datlab)\nmodelsummary(modlab, coef_rename = TRUE)\n\n \n\n \n \n\ntinytable_jd3dgp5uqqoiirbwh47q\n\n\n \n\n \n (1)\n \n\n\n(Intercept) \n 14.850 \n \n\n \n (11.923)\n \n\nHorsepower \n -0.011 \n \n\n \n (0.082) \n \n\ndrat \n 3.612 \n \n\n \n (3.019) \n \n\nCylinders [6] \n -4.091 \n \n\n \n (1.881) \n \n\nCylinders [8] \n -5.019 \n \n\n \n (3.056) \n \n\nHorsepower × drat\n -0.006 \n \n\n \n (0.021) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.784 \n \n\nR2 Adj. \n 0.742 \n \n\nAIC \n 169.7 \n \n\nBIC \n 180.0 \n \n\nLog.Lik. \n -77.860 \n \n\nF \n 18.871 \n \n\nRMSE \n 2.76 \n \n\n\n\n\n \n\n# coef_rename: unnamed vector of length equal to the number of terms in the final table\nm <- lm(hp ~ mpg + factor(cyl), data = mtcars)\nmodelsummary(m, coef_omit = -(3:4), coef_rename = c(\"Cyl 6\", \"Cyl 8\"))\n\n \n\n \n \n\ntinytable_8yhhdupm1wl2yboqg1ru\n\n\n \n\n \n (1)\n \n\n\nCyl 6 \n 16.623 \n \n\n \n (23.197)\n \n\nCyl 8 \n 88.105 \n \n\n \n (28.819)\n \n\nNum.Obs.\n 32 \n \n\nR2 \n 0.737 \n \n\nR2 Adj. \n 0.709 \n \n\nAIC \n 327.7 \n \n\nBIC \n 335.0 \n \n\nLog.Lik.\n -158.831\n \n\nF \n 26.122 \n \n\nRMSE \n 34.62 \n \n\n\n\n\n \n\n# coef_map\nmodelsummary(models, coef_map = c('Volume' = 'Large', 'Height' = 'Tall'))\n\n \n\n \n \n\ntinytable_jvpbqyxyspsg4mlxlv5s\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nLarge \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nTall \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nNum.Obs.\n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik.\n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, coef_map = c('Volume', 'Height'))\n\n \n\n \n \n\ntinytable_cht3225tx0vqxyzy66z3\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nNum.Obs.\n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik.\n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# coef_omit: omit the first and second coefficients\nmodelsummary(models, coef_omit = 1:2)\n\n \n\n \n \n\ntinytable_zg88j5z13olou34egikk\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs.\n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik.\n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# coef_omit: omit coefficients matching one substring\nmodelsummary(models, coef_omit = \"ei\", gof_omit = \".*\")\n\n \n\n \n \n\ntinytable_aiuatsml2moa4l7samru\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\n\n\n\n \n\n# coef_omit: omit a specific coefficient\nmodelsummary(models, coef_omit = \"^Volume$\", gof_omit = \".*\")\n\n \n\n \n \n\ntinytable_90yc5ohf513hvzx7jhep\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\n\n\n\n \n\n# coef_omit: omit coefficients matching either one of two substring\n#modelsummary(models, coef_omit = \"ei|rc\", gof_omit = \".*\")\n\n# coef_omit: keep coefficients starting with a substring (using a negative lookahead)\n#modelsummary(models, coef_omit = \"^(?!Vol)\", gof_omit = \".*\")\n\n# coef_omit: keep coefficients matching a substring\nmodelsummary(models, coef_omit = \"^(?!.*ei|.*pt)\", gof_omit = \".*\")\n\n \n\n \n \n\ntinytable_leo6hlsmpbh7w23dcxet\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\n\n\n\n \n\n# shape: multinomial model\nlibrary(nnet)\nmulti <- multinom(factor(cyl) ~ mpg + hp, data = mtcars, trace = FALSE) \n\n# shape: term names and group ids in rows, models in columns\nmodelsummary(multi, shape = response ~ model)\n\n \n\n \n \n\ntinytable_2x6f6mtmn6m96xomt61h\n\n\n \n\n \n response\n (1)\n \n\n\n(Intercept)\n 6\n 0.500 \n \n\n \n \n (41.760) \n \n\n \n 8\n 8.400 \n \n\n \n \n (0.502) \n \n\nmpg \n 6\n -83.069 \n \n\n \n \n (416.777)\n \n\n \n 8\n -120.167 \n \n\n \n \n (508.775)\n \n\nhp \n 6\n 16.230 \n \n\n \n \n (81.808) \n \n\n \n 8\n 20.307 \n \n\n \n \n (87.777) \n \n\nNum.Obs. \n \n 32 \n \n\nR2 \n \n 1.000 \n \n\nR2 Adj. \n \n 0.971 \n \n\nAIC \n \n 12.0 \n \n\nBIC \n \n 20.8 \n \n\nRMSE \n \n 0.00 \n \n\n\n\n\n \n\n# shape: term names and group ids in rows in a single column\nmodelsummary(multi, shape = term : response ~ model)\n\n \n\n \n \n\ntinytable_qp9b1b3zy0ngjz4s1ixu\n\n\n \n\n \n (1)\n \n\n\n(Intercept) 6\n 0.500 \n \n\n \n (41.760) \n \n\nmpg 6 \n -83.069 \n \n\n \n (416.777)\n \n\nhp 6 \n 16.230 \n \n\n \n (81.808) \n \n\n(Intercept) 8\n 8.400 \n \n\n \n (0.502) \n \n\nmpg 8 \n -120.167 \n \n\n \n (508.775)\n \n\nhp 8 \n 20.307 \n \n\n \n (87.777) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 1.000 \n \n\nR2 Adj. \n 0.971 \n \n\nAIC \n 12.0 \n \n\nBIC \n 20.8 \n \n\nRMSE \n 0.00 \n \n\n\n\n\n \n\n# shape: term names in rows and group ids in columns\nmodelsummary(multi, shape = term ~ response:model)\n\n \n\n \n \n\ntinytable_kkvdw7jviuquvn5wqnzs\n\n\n \n\n\n \n(1)\n\n\n \n 6\n 8\n \n\n\n\n(Intercept)\n 0.500 \n 8.400 \n \n\n \n (41.760) \n (0.502) \n \n\nmpg \n -83.069 \n -120.167 \n \n\n \n (416.777)\n (508.775)\n \n\nhp \n 16.230 \n 20.307 \n \n\n \n (81.808) \n (87.777) \n \n\nNum.Obs. \n 32 \n \n \n\nR2 \n 1.000 \n \n \n\nR2 Adj. \n 0.971 \n \n \n\nAIC \n 12.0 \n \n \n\nBIC \n 20.8 \n \n \n\nRMSE \n 0.00 \n \n \n\n\n\n\n \n\n# shape = \"rcollapse\"\npanels <- list(\n \"Panel A: MPG\" = list(\n \"A\" = lm(mpg ~ hp, data = mtcars),\n \"B\" = lm(mpg ~ hp + factor(gear), data = mtcars)),\n \"Panel B: Displacement\" = list(\n \"A\" = lm(disp ~ hp, data = mtcars),\n \"C\" = lm(disp ~ hp + factor(gear), data = mtcars))\n)\n\n# shape = \"cbind\"\nmodelsummary(panels, shape = \"cbind\")\n\n \n\n \n \n\ntinytable_i3nyohz4ryvw87xcdrvr\n\n\n \n\n\n \nPanel A: MPG\nPanel B: Displacement\n\n\n \n A\n B\n A \n C\n \n\n\n\n(Intercept) \n 30.099 \n 27.882 \n 20.992 \n 112.093 \n \n\n \n (1.634)\n (2.109)\n (32.607)\n (34.704)\n \n\nhp \n -0.068 \n -0.067 \n 1.430 \n 1.216 \n \n\n \n (0.010)\n (0.011)\n (0.202) \n (0.182) \n \n\nfactor(gear)4\n \n 2.635 \n \n -97.923 \n \n\n \n \n (1.552)\n \n (25.532)\n \n\nfactor(gear)5\n \n 6.575 \n \n -147.495\n \n\n \n \n (1.643)\n \n (27.030)\n \n\nNum.Obs. \n 32 \n 32 \n 32 \n 32 \n \n\nR2 \n 0.602 \n 0.753 \n 0.626 \n 0.842 \n \n\nR2 Adj. \n 0.589 \n 0.726 \n 0.613 \n 0.825 \n \n\nAIC \n 181.2 \n 170.0 \n 372.8 \n 349.3 \n \n\nBIC \n 185.6 \n 177.4 \n 377.2 \n 356.6 \n \n\nLog.Lik. \n -87.619\n -80.024\n -183.412\n -169.643\n \n\nF \n 45.460 \n 28.407 \n 50.128 \n 49.611 \n \n\nRMSE \n 3.74 \n 2.95 \n 74.64 \n 48.54 \n \n\n\n\n\n \n\nmodelsummary(\n panels,\n shape = \"rbind\",\n gof_map = c(\"nobs\", \"r.squared\"))\n\n \n\n \n \n\ntinytable_8g8cbr2e6rkzqw58oxza\n\n\n \n\n \n A\n B\n C\n \n\n\n(Intercept) \n 30.099 \n 27.882 \n \n \n\n \n (1.634) \n (2.109)\n \n \n\nhp \n -0.068 \n -0.067 \n \n \n\n \n (0.010) \n (0.011)\n \n \n\nfactor(gear)4\n \n 2.635 \n \n \n\n \n \n (1.552)\n \n \n\nfactor(gear)5\n \n 6.575 \n \n \n\n \n \n (1.643)\n \n \n\nNum.Obs. \n 32 \n 32 \n \n \n\nR2 \n 0.602 \n 0.753 \n \n \n\n(Intercept) \n 20.992 \n \n 112.093 \n \n\n \n (32.607)\n \n (34.704)\n \n\nhp \n 1.430 \n \n 1.216 \n \n\n \n (0.202) \n \n (0.182) \n \n\nfactor(gear)4\n \n \n -97.923 \n \n\n \n \n \n (25.532)\n \n\nfactor(gear)5\n \n \n -147.495\n \n\n \n \n \n (27.030)\n \n\nNum.Obs. \n 32 \n \n 32 \n \n\nR2 \n 0.626 \n \n 0.842 \n \n\n\n\n\n \n\n# title\nmodelsummary(models, title = 'This is the title')\n\n \n\n \n \n\ntinytable_4i850ve155sa8cck22rk\n\n\n \n\nThis is the title\n \n \n Bivariate\n Multivariate\n \n\n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# title with LaTeX label (for numbering and referencing)\nmodelsummary(models, title = 'This is the title \\\\label{tab:description}')\n\n \n\n \n \n\ntinytable_8m7o5gclykcsbtnqn7gh\n\n\n \n\nThis is the title \\label{tab:description}\n \n \n Bivariate\n Multivariate\n \n\n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# add_rows\nrows <- tibble::tribble(~term, ~Bivariate, ~Multivariate,\n 'Empty row', '-', '-',\n 'Another empty row', '?', '?')\nattr(rows, 'position') <- c(1, 3)\nmodelsummary(models, add_rows = rows)\n\n \n\n \n \n\ntinytable_u2tqoc5p422bx49w9j60\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nEmpty row \n - \n - \n \n\n(Intercept) \n -6.188 \n 10.816 \n \n\nAnother empty row\n ? \n ? \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# notes\nmodelsummary(models, notes = list('A first note', 'A second note'))\n\n \n\n \n \n\ntinytable_0ghxu5xl138u2hrnedt4\n\n\n \n\n \n Bivariate\n Multivariate\n \n\nA first note\nA second note\n\n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# gof_map: tribble\nlibrary(tibble)\ngm <- tribble(\n ~raw, ~clean, ~fmt,\n \"r.squared\", \"R Squared\", 5)\nmodelsummary(models, gof_map = gm)\n\n \n\n \n \n\ntinytable_3znxwmq3oulnxnzngn8k\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nR Squared \n 0.26965\n 0.94080", + "crumbs": [ + "Get started", + "Functions", + "`modelsummary`" + ] + }, + { + "objectID": "man/modelsummary.html#model-summary-tables", + "href": "man/modelsummary.html#model-summary-tables", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Create beautiful and customizable tables to summarize several statistical models side-by-side. This function supports dozens of statistical models, and it can produce tables in HTML, LaTeX, Word, Markdown, Typst, PDF, PowerPoint, Excel, RTF, JPG, or PNG. The appearance of the tables can be customized extensively by specifying the output argument, and by using functions from one of the supported table customization packages: tinytable, kableExtra, gt, flextable, huxtable, DT. For more information, see the Details and Examples sections below, and the vignettes on the modelsummary website: https://modelsummary.com/\n\n\nThe modelsummary Vignette includes dozens of examples of tables with extensive customizations.\n\n\nThe Appearance Vignette shows how to modify the look of tables.\n\n\nmodelsummary(\n models,\n output = \"default\",\n fmt = 3,\n estimate = \"estimate\",\n statistic = \"std.error\",\n vcov = NULL,\n conf_level = 0.95,\n exponentiate = FALSE,\n stars = FALSE,\n shape = term + statistic ~ model,\n coef_map = NULL,\n coef_omit = NULL,\n coef_rename = FALSE,\n gof_map = NULL,\n gof_omit = NULL,\n gof_function = NULL,\n group_map = NULL,\n add_columns = NULL,\n add_rows = NULL,\n align = NULL,\n notes = NULL,\n title = NULL,\n escape = TRUE,\n ...\n)\n\n\n\n\n\nmodels\n\n\na model, (named) list of models, or nested list of models.\n\n\nSingle model: modelsummary(model)\n\n\nUnnamed list of models: modelsummary(list(model1, model2))\n\n\nModels are labelled automatically. The default label style can be altered by setting a global option. See below.\n\n\n\n\nNamed list of models: modelsummary(list(“A”=model1, “B”=model2))\n\n\nModels are labelled using the list names.\n\n\n\n\nNested list of models:\n\n\nWhen using the shape argument with \"rbind\", \"rcollapse\", or \"cbind\" values, models can be a nested list of models to display \"panels\" or \"stacks\" of regression models. See the shape argument documentation and examples below.\n\n\n\n\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_decimal(digits = 2, pdigits = 3): Decimal digits for estimate and p values\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_term(“(Intercept)” = 1, “X” = 2): Format terms differently\n\n\nfmt = fmt_statistic(“estimate” = 1, “r.squared” = 6): Format statistics differently.\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\nstring:\n\n\nNote on LaTeX output: To ensure proper typography, all numeric entries are enclosed in the command, which requires the siunitx package to be loaded in the LaTeX preamble. This behavior can be altered with global options. See the ‘Details’ section.\n\n\n\n\n\n\nestimate\n\n\na single string or a character vector of length equal to the number of models. Valid entries include any column name of the data.frame produced by get_estimates(model), and strings with curly braces compatible with the glue package format. Examples:\n\n\n“estimate”\n\n\n“{estimate} ({std.error}){stars}”\n\n\n“{estimate} [{conf.low}, {conf.high}]”\n\n\n\n\n\n\nstatistic\n\n\nvector of strings or glue strings which select uncertainty statistics to report vertically below the estimate. NULL omits all uncertainty statistics.\n\n\n\"conf.int\", \"std.error\", \"statistic\", \"p.value\", \"conf.low\", \"conf.high\", or any column name produced by get_estimates(model)\n\n\nglue package strings with braces, with or without R functions, such as:\n\n\n“{p.value} [{conf.low}, {conf.high}]”\n\n\n“Std.Error: {std.error}”\n\n\n“{exp(estimate) * std.error}”\n\n\nNumbers are automatically rounded and converted to strings. To apply functions to their numeric values, as in the last glue example, users must set fmt=NULL.\n\n\nParentheses are added automatically unless the string includes glue curly braces {}.\n\n\n\n\nNotes:\n\n\nThe names of the statistic are used a column names when using the shape argument to display statistics as columns:\n\n\nstatistic=c(“p”=“p.value”, “[”=”conf.low”, ”]”=“conf.high”)\n\n\n\n\nSome statistics are not supported for all models. See column names in get_estimates(model), and visit the website to learn how to add custom statistics.\n\n\n\n\n\n\n\n\nvcov\n\n\nrobust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):\n\n\nNULL returns the default uncertainty estimates of the model object\n\n\nstring, vector, or (named) list of strings. \"iid\", \"classical\", and \"constant\" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings \"HC\", \"HC0\", \"HC1\" (alias: \"stata\"), \"HC2\", \"HC3\" (alias: \"robust\"), \"HC4\", \"HC4m\", \"HC5\", \"HAC\", \"NeweyWest\", \"Andrews\", \"panel-corrected\", \"outer-product\", and \"weave\" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. \"BS\", \"bootstrap\", \"residual\", \"mammen\", \"webb\", \"xy\", \"wild\" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (…), but it is safer to define your own custom functions as described in the next bullet.\n\n\nfunction or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).\n\n\nformula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).\n\n\nnamed list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.\n\n\na named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.\n\n\n\n\n\n\nconf_level\n\n\nnumeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models.\n\n\n\n\nexponentiate\n\n\nTRUE, FALSE, or logical vector of length equal to the number of models. If TRUE, the estimate, conf.low, and conf.high statistics are exponentiated, and the std.error is transformed to exp(estimate)*std.error.\n\n\n\n\nstars\n\n\nto indicate statistical significance\n\n\nFALSE (default): no significance stars.\n\n\nTRUE: +=.1, =.05, =.01, =0.001\n\n\nNamed numeric vector for custom stars such as c(’*’ = .1, ‘+’ = .05)\n\n\nNote: a legend will not be inserted at the bottom of the table when the estimate or statistic arguments use \"glue strings\" with stars.\n\n\n\n\n\n\nshape\n\n\nNULL, formula, or string which determines the shape of a table.\n\n\nNULL: Default shape with terms in rows and models in columns.\n\n\nFormula: The left side determines what appears on rows, and the right side determines what appears on columns. The formula can include one or more group identifier(s) to display related terms together, which can be useful for models with multivariate outcomes or grouped coefficients (See examples section below). The group identifier(s) must be column names produced by: get_estimates(model). The group identifier(s) can be combined with the term identifier in a single column by using the colon to represent an interaction. If an incomplete formula is supplied (e.g., ~statistic), modelsummary tries to complete it automatically. Goodness-of-fit statistics are only appended to the bottom of the table when model is on the right hand side of the formula (i.e., columns). Potential shape values include:\n\n\nterm + statistic ~ model: default\n\n\nterm ~ model + statistic: statistics in separate columns\n\n\nmodel + statistic ~ term: models in rows and terms in columns\n\n\nterm + response + statistic ~ model: term and group id in separate columns\n\n\nterm : response + statistic ~ model: term and group id in a single column\n\n\nterm ~ response\n\n\n\n\nString: \"cbind\", \"rbind\", \"rcollapse\"\n\n\n\"cbind\": side-by-side models with autmoatic spanning column headers to group models (tinytable only feature).\n\n\n\"rbind\" or \"rcollapse\": \"panels\" or \"stacks\" of regression models.\n\n\nthe models argument must be a (potentially named) nested list of models.\n\n\n\n\nUnnamed nested list with 2 panels: list(list(model1, model2), list(model3, model4))\n\n\nNamed nested list with 2 panels: list(“Panel A” = list(model1, model2), “Panel B” = list(model3, model4))\n\n\nNamed panels and named models: list(“Panel A” = list(“(I)” = model1, “(II)” = model2), “Panel B” = list(“(I)” = model3, “(II)” = model4))\n\n\n\n\n\"rbind\": Bind the rows of independent regression tables\n\n\n\"rcollapse\": Bind the rows of regression tables and create a panel at the bottom where we \"collapse\" goodness-of-fit statistics which are identical across models.\n\n\n\n\n\n\n\n\ncoef_map\n\n\ncharacter vector. Subset, rename, and reorder coefficients. Coefficients omitted from this vector are omitted from the table. The order of the vector determines the order of the table. coef_map can be a named or an unnamed character vector. If coef_map is a named vector, its values define the labels that must appear in the table, and its names identify the original term names stored in the model object: c(“hp:mpg”=“HPxM/G”). See Examples section below.\n\n\n\n\ncoef_omit\n\n\ninteger vector or regular expression to identify which coefficients to omit (or keep) from the table. Positive integers determine which coefficients to omit. Negative integers determine which coefficients to keep. A regular expression can be used to omit coefficients, and perl-compatible \"negative lookaheads\" can be used to specify which coefficients to keep in the table. Examples:\n\n\nc(2, 3, 5): omits the second, third, and fifth coefficients.\n\n\nc(-2, -3, -5): negative values keep the second, third, and fifth coefficients.\n\n\n“ei”: omit coefficients matching the \"ei\" substring.\n\n\n“^Volume$”: omit the \"Volume\" coefficient.\n\n\n“ei|rc”: omit coefficients matching either the \"ei\" or the \"rc\" substrings.\n\n\n“^(?!Vol)”: keep coefficients starting with \"Vol\" (inverse match using a negative lookahead).\n\n\n“^(?!.*ei)“: keep coefficients matching the”ei\" substring.\n\n\n“^(?!.ei|.pt)”: keep coefficients matching either the \"ei\" or the \"pt\" substrings.\n\n\nSee the Examples section below for complete code.\n\n\n\n\n\n\ncoef_rename\n\n\nlogical, named or unnamed character vector, or function\n\n\nLogical: TRUE renames variables based on the \"label\" attribute of each column. See the Example section below.\n\n\nUnnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.\n\n\nNamed character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c(\"hp:mpg\"=\"hp X mpg\")\n\n\nFunction: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)\n\n\n\n\n\n\ngof_map\n\n\nrename, reorder, and omit goodness-of-fit statistics and other model information. This argument accepts 4 types of values:\n\n\nNULL (default): the modelsummary::gof_map dictionary is used for formatting, and all unknown statistic are included.\n\n\ncharacter vector: \"all\", \"none\", or a vector of statistics such as c(“rmse”, “nobs”, “r.squared”). Elements correspond to colnames in the data.frame produced by get_gof(model). The modelsummary::gof_map default dictionary is used to format and rename statistics.\n\n\nNA: excludes all statistics from the bottom part of the table.\n\n\ndata.frame with 3 columns named \"raw\", \"clean\", \"fmt\". Unknown statistics are omitted. See the ‘Examples’ section below. The fmt column in this data frame only accepts integers. For more flexibility, use a list of lists, as described in the next bullet.\n\n\nlist of lists, each of which includes 3 elements named \"raw\", \"clean\", \"fmt\". Unknown statistics are omitted. See the ‘Examples section below’.\n\n\n\n\n\n\ngof_omit\n\n\nstring regular expression (perl-compatible) used to determine which statistics to omit from the bottom section of the table. A \"negative lookahead\" can be used to specify which statistics to keep in the table. Examples:\n\n\n“IC”: omit statistics matching the \"IC\" substring.\n\n\n“BIC|AIC”: omit statistics matching the \"AIC\" or \"BIC\" substrings.\n\n\n“^(?!.*IC)“: keep statistics matching the”IC\" substring.\n\n\n\n\n\n\ngof_function\n\n\nfunction which accepts a model object in the model argument and returns a 1-row data.frame with one custom goodness-of-fit statistic per column.\n\n\n\n\ngroup_map\n\n\nnamed or unnamed character vector. Subset, rename, and reorder coefficient groups specified a grouping variable specified in the shape argument formula. This argument behaves like coef_map.\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as #’ your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the columns positions. See Examples section below.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.\n\n\n\n\n\n\nThe modelsummary_list output is a lightweight format which can be used to save model results, so they can be fed back to modelsummary later to avoid extracting results again.\nWhen a file name with a valid extension is supplied to the output argument, the table is written immediately to file. If you want to customize your table by post-processing it with an external package, you need to choose a different output format and saving mechanism. Unfortunately, the approach differs from package to package:\n\n\ntinytable: set output=“tinytable”, post-process your table, and use the tinytable::save_tt function.\n\n\ngt: set output=“gt”, post-process your table, and use the gt::gtsave function.\n\n\nkableExtra: set output to your destination format (e.g., \"latex\", \"html\", \"markdown\"), post-process your table, and use kableExtra::save_kable function.\n\n\n\nTo use a string such as \"robust\" or \"HC0\", your model must be supported by the sandwich package. This includes objects such as: lm, glm, survreg, coxph, mlogit, polr, hurdle, zeroinfl, and more.\nNULL, \"classical\", \"iid\", and \"constant\" are aliases which do not modify uncertainty estimates and simply report the default standard errors stored in the model object.\nOne-sided formulas such as ~clusterid are passed to the sandwich::vcovCL function.\nMatrices and functions producing variance-covariance matrices are first passed to lmtest. If this does not work, modelsummary attempts to take the square root of the diagonal to adjust \"std.error\", but the other uncertainty estimates are not be adjusted.\nNumeric vectors are formatted according to fmt and placed in brackets. Character vectors printed as given, without parentheses.\nIf your model type is supported by the lmtest package, the vcov argument will try to use that package to adjust all the uncertainty estimates, including \"std.error\", \"statistic\", \"p.value\", and \"conf.int\". If your model is not supported by lmtest, only the \"std.error\" will be adjusted by, for example, taking the square root of the matrix’s diagonal.\n\na regression table in a format determined by the output argument.\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\nIt can take a long time to compute and extract summary statistics from certain models (e.g., Bayesian). In those cases, users can parallelize the process. Since parallelization occurs at the model level, no speedup is available for tables with a single model. Users on mac or linux can launch parallel computation using the built-in parallel package. All they need to do is supply a mc.cores argument which will be pushed forward to the parallel::mclapply function:\n\nmodelsummary(model_list, mc.cores = 5)\n\n\nAll users can also use the future.apply package to parallelize model summaries. For example, to use 4 cores to extract results:\n\nlibrary(future.apply)\nplan(multicore, workers = 4)\noptions(\"modelsummary_future\" = TRUE)\nmodelsummary(model_list)\n\n\nNote that the \"multicore\" plan only parallelizes under mac or linux. Windows users can use plan(multisession) instead. However, note that the first time modelsummary() is called under multisession can be a fair bit longer, because of extra costs in passing data to and loading required packages on to workers. Subsequent calls to modelsummary() will often be much faster.\nSome users have reported difficult to reproduce errors when using the future package with some packages. The future parallelization in modelsummary can be disabled by calling:\noptions(“modelsummary_future” = FALSE)\n\nArel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’\n\n\nlibrary(modelsummary)\n\n\n# The `modelsummary` website includes \\emph{many} examples and tutorials:\n# https://modelsummary.com\n\nlibrary(modelsummary)\n\n# load data and estimate models\nutils::data(trees)\nmodels <- list()\nmodels[['Bivariate']] <- lm(Girth ~ Height, data = trees)\nmodels[['Multivariate']] <- lm(Girth ~ Height + Volume, data = trees)\n\n# simple table\nmodelsummary(models)\n\n \n\n \n \n\ntinytable_mcj4zhgw5up1bpuiazvv\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# statistic\nmodelsummary(models, statistic = NULL)\n\n \n\n \n \n\ntinytable_qrrm1ns1xhp54009wgtz\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\nHeight \n 0.256 \n -0.045 \n \n\nVolume \n \n 0.195 \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = 'p.value')\n\n \n\n \n \n\ntinytable_he4qy7ao5dkgshldjxv8\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (0.308)\n (\n \n\n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.003)\n (0.119) \n \n\nVolume \n \n 0.195 \n \n\n \n \n (\n \n\n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = 'statistic')\n\n \n\n \n \n\ntinytable_jv2mi0vsnbljzcxn55oe\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (-1.038)\n (5.482) \n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (3.272) \n (-1.609)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (17.816)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = 'conf.int', conf_level = 0.99)\n\n \n\n \n \n\ntinytable_qhae4g99mpkj94vw8zz2\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n [-22.617, 10.240]\n [5.364, 16.269]\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n [0.040, 0.471] \n [-0.124, 0.033]\n \n\nVolume \n \n 0.195 \n \n\n \n \n [0.165, 0.225] \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, statistic = c(\"t = {statistic}\",\n \"se = {std.error}\",\n \"conf.int\"))\n\n \n\n \n \n\ntinytable_bd2w1unh5si2ob1nwap9\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n t = -1.038 \n t = 5.482 \n \n\n \n se = 5.960 \n se = 1.973 \n \n\n \n [-18.378, 6.002]\n [6.774, 14.858]\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n t = 3.272 \n t = -1.609 \n \n\n \n se = 0.078 \n se = 0.028 \n \n\n \n [0.096, 0.416] \n [-0.103, 0.012]\n \n\nVolume \n \n 0.195 \n \n\n \n \n t = 17.816 \n \n\n \n \n se = 0.011 \n \n\n \n \n [0.173, 0.218] \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# estimate\nmodelsummary(models,\n statistic = NULL,\n estimate = \"{estimate} [{conf.low}, {conf.high}]\")\n\n \n\n \n \n\ntinytable_idwa3y8zpe8oumq9dmbj\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 [-18.378, 6.002]\n 10.816 [6.774, 14.858]\n \n\nHeight \n 0.256 [0.096, 0.416] \n -0.045 [-0.103, 0.012]\n \n\nVolume \n \n 0.195 [0.173, 0.218] \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models,\n estimate = c(\"{estimate}{stars}\",\n \"{estimate} ({std.error})\"))\n\n \n\n \n \n\ntinytable_pkh9uv1j7tevhruib11c\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 (1.973)\n \n\n \n (5.960)\n (1.973) \n \n\nHeight \n 0.256**\n -0.045 (0.028)\n \n\n \n (0.078)\n (0.028) \n \n\nVolume \n \n 0.195 (0.011) \n \n\n \n \n (0.011) \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116 \n \n\nF \n 10.707 \n 222.471 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# vcov\nmodelsummary(models, vcov = \"robust\")\n\n \n\n \n \n\ntinytable_dohd2tu9jincrqw9navw\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (6.717)\n (2.544)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.090)\n (0.035)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.014)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 8.021 \n 100.427\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n HC3 \n HC3 \n \n\n\n\n\n \n\nmodelsummary(models, vcov = list(\"classical\", \"stata\"))\n\n \n\n \n \n\ntinytable_h4yy74l84znfd2ulobjw\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (2.261)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.031)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.012)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 151.435\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n IID \n HC1 \n \n\n\n\n\n \n\nmodelsummary(models, vcov = sandwich::vcovHC)\n\n \n\n \n \n\ntinytable_x9abw2if38t63xnw5z4c\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (6.717)\n (2.544)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.090)\n (0.035)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.014)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Custom \n Custom \n \n\n\n\n\n \n\nmodelsummary(models,\n vcov = list(stats::vcov, sandwich::vcovHC))\n\n \n\n \n \n\ntinytable_zx024ku0vvosj0cx9h3e\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (2.544)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.035)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.014)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Custom \n Custom \n \n\n\n\n\n \n\nmodelsummary(models,\n vcov = list(c(\"(Intercept)\"=\"\", \"Height\"=\"!\"),\n c(\"(Intercept)\"=\"\", \"Height\"=\"!\", \"Volume\"=\"!!\")))\n\n \n\n \n \n\ntinytable_gs5awfdrsxdfx7mp2ve7\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n ! \n ! \n \n\nVolume \n \n 0.195 \n \n\n \n \n !! \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Custom \n Custom \n \n\n\n\n\n \n\n# vcov with custom names\nmodelsummary(\n models,\n vcov = list(\"Stata Corp\" = \"stata\",\n \"Newey Lewis & the News\" = \"NeweyWest\"))\n\n \n\n \n \n\ntinytable_60fu490ojr1t5pblfiij\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (6.171) \n (1.839) \n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.083) \n (0.022) \n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.007) \n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061 \n -35.116 \n \n\nRMSE \n 2.64 \n 0.75 \n \n\nStd.Errors \n Stata Corp\n Newey Lewis & the News\n \n\n\n\n\n \n\n# fmt\nmod <- lm(mpg ~ hp + drat + qsec, data = mtcars)\n\nmodelsummary(mod, fmt = 3)\n\n \n\n \n \n\ntinytable_x3h0ityo4f865lgcnncl\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.737 \n \n\n \n (13.020)\n \n\nhp \n -0.058 \n \n\n \n (0.014) \n \n\ndrat \n 4.429 \n \n\n \n (1.292) \n \n\nqsec \n -0.284 \n \n\n \n (0.489) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_significant(3))\n\n \n\n \n \n\ntinytable_j6f4s5owmade787l5bsb\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7 \n \n\n \n (13.0) \n \n\nhp \n -0.0580 \n \n\n \n (0.0142)\n \n\ndrat \n 4.43 \n \n\n \n (1.29) \n \n\nqsec \n -0.284 \n \n\n \n (0.489) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = NULL)\n\n \n\n \n \n\ntinytable_f0exllns2gcztktcjygr\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7366200480466 \n \n\n \n (13.0197907534221) \n \n\nhp \n -0.057972987581075 \n \n\n \n (0.014208609097443)\n \n\ndrat \n 4.42875344653986 \n \n\n \n (1.29169225236228) \n \n\nqsec \n -0.284074290906574 \n \n\n \n (0.489229280152) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_decimal(4))\n\n \n\n \n \n\ntinytable_9uvqs6k8qkl5zmtdi5cr\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7366 \n \n\n \n (13.0198)\n \n\nhp \n -0.0580 \n \n\n \n (0.0142) \n \n\ndrat \n 4.4288 \n \n\n \n (1.2917) \n \n\nqsec \n -0.2841 \n \n\n \n (0.4892) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_sprintf(\"%.5f\"))\n\n \n\n \n \n\ntinytable_skia0w0qpih8cryrs5x7\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.73662 \n \n\n \n (13.01979)\n \n\nhp \n -0.05797 \n \n\n \n (0.01421) \n \n\ndrat \n 4.42875 \n \n\n \n (1.29169) \n \n\nqsec \n -0.28407 \n \n\n \n (0.48923) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_statistic(estimate = 4, conf.int = 1), statistic = \"conf.int\")\n\n \n\n \n \n\ntinytable_ye03yw1s7yjnv916nfq1\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.7366 \n \n\n \n [-8.9, 44.4]\n \n\nhp \n -0.0580 \n \n\n \n [-0.1, 0.0] \n \n\ndrat \n 4.4288 \n \n\n \n [1.8, 7.1] \n \n\nqsec \n -0.2841 \n \n\n \n [-1.3, 0.7] \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nmodelsummary(mod, fmt = fmt_term(hp = 4, drat = 1, default = 2))\n\n \n\n \n \n\ntinytable_f3jackzt6fgrtnoisuf6\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 17.74 \n \n\n \n (13.02) \n \n\nhp \n -0.0580 \n \n\n \n (0.0142)\n \n\ndrat \n 4.4 \n \n\n \n (1.3) \n \n\nqsec \n -0.28 \n \n\n \n (0.49) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.744 \n \n\nR2 Adj. \n 0.717 \n \n\nAIC \n 171.1 \n \n\nBIC \n 178.5 \n \n\nLog.Lik. \n -80.561 \n \n\nF \n 27.161 \n \n\nRMSE \n 3.00 \n \n\n\n\n\n \n\nm <- lm(mpg ~ I(hp * 1000) + drat, data = mtcars)\nf <- function(x) format(x, digits = 3, nsmall = 2, scientific = FALSE, trim = TRUE)\nmodelsummary(m, fmt = f, gof_map = NA)\n\n \n\n \n \n\ntinytable_2w2n9juxyb78dfqqqc09\n\n\n \n\n \n (1)\n \n\n\n(Intercept) \n 10.7898612 \n \n\n \n (5.07775160)\n \n\nI(hp * 1000)\n -0.0000518 \n \n\n \n (0.00000929)\n \n\ndrat \n 4.6981578 \n \n\n \n (1.19163348)\n \n\n\n\n\n \n\n# coef_rename\nmodelsummary(models, coef_rename = c('Volume' = 'Large', 'Height' = 'Tall'))\n\n \n\n \n \n\ntinytable_4pwqwj6b87mwuxkuka2v\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nTall \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nLarge \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, coef_rename = toupper)\n\n \n\n \n \n\ntinytable_368s8x0z4lodkykk2jsj\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(INTERCEPT)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHEIGHT \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVOLUME \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, coef_rename = coef_rename)\n\n \n\n \n \n\ntinytable_36nrj7aeah44jz3si96q\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# coef_rename = TRUE for variable labels\ndatlab <- mtcars\ndatlab$cyl <- factor(datlab$cyl)\nattr(datlab$hp, \"label\") <- \"Horsepower\"\nattr(datlab$cyl, \"label\") <- \"Cylinders\"\nmodlab <- lm(mpg ~ hp * drat + cyl, data = datlab)\nmodelsummary(modlab, coef_rename = TRUE)\n\n \n\n \n \n\ntinytable_jd3dgp5uqqoiirbwh47q\n\n\n \n\n \n (1)\n \n\n\n(Intercept) \n 14.850 \n \n\n \n (11.923)\n \n\nHorsepower \n -0.011 \n \n\n \n (0.082) \n \n\ndrat \n 3.612 \n \n\n \n (3.019) \n \n\nCylinders [6] \n -4.091 \n \n\n \n (1.881) \n \n\nCylinders [8] \n -5.019 \n \n\n \n (3.056) \n \n\nHorsepower × drat\n -0.006 \n \n\n \n (0.021) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.784 \n \n\nR2 Adj. \n 0.742 \n \n\nAIC \n 169.7 \n \n\nBIC \n 180.0 \n \n\nLog.Lik. \n -77.860 \n \n\nF \n 18.871 \n \n\nRMSE \n 2.76 \n \n\n\n\n\n \n\n# coef_rename: unnamed vector of length equal to the number of terms in the final table\nm <- lm(hp ~ mpg + factor(cyl), data = mtcars)\nmodelsummary(m, coef_omit = -(3:4), coef_rename = c(\"Cyl 6\", \"Cyl 8\"))\n\n \n\n \n \n\ntinytable_8yhhdupm1wl2yboqg1ru\n\n\n \n\n \n (1)\n \n\n\nCyl 6 \n 16.623 \n \n\n \n (23.197)\n \n\nCyl 8 \n 88.105 \n \n\n \n (28.819)\n \n\nNum.Obs.\n 32 \n \n\nR2 \n 0.737 \n \n\nR2 Adj. \n 0.709 \n \n\nAIC \n 327.7 \n \n\nBIC \n 335.0 \n \n\nLog.Lik.\n -158.831\n \n\nF \n 26.122 \n \n\nRMSE \n 34.62 \n \n\n\n\n\n \n\n# coef_map\nmodelsummary(models, coef_map = c('Volume' = 'Large', 'Height' = 'Tall'))\n\n \n\n \n \n\ntinytable_jvpbqyxyspsg4mlxlv5s\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nLarge \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nTall \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nNum.Obs.\n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik.\n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\nmodelsummary(models, coef_map = c('Volume', 'Height'))\n\n \n\n \n \n\ntinytable_cht3225tx0vqxyzy66z3\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nNum.Obs.\n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik.\n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# coef_omit: omit the first and second coefficients\nmodelsummary(models, coef_omit = 1:2)\n\n \n\n \n \n\ntinytable_zg88j5z13olou34egikk\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs.\n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik.\n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# coef_omit: omit coefficients matching one substring\nmodelsummary(models, coef_omit = \"ei\", gof_omit = \".*\")\n\n \n\n \n \n\ntinytable_aiuatsml2moa4l7samru\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\n\n\n\n \n\n# coef_omit: omit a specific coefficient\nmodelsummary(models, coef_omit = \"^Volume$\", gof_omit = \".*\")\n\n \n\n \n \n\ntinytable_90yc5ohf513hvzx7jhep\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\n\n\n\n \n\n# coef_omit: omit coefficients matching either one of two substring\n#modelsummary(models, coef_omit = \"ei|rc\", gof_omit = \".*\")\n\n# coef_omit: keep coefficients starting with a substring (using a negative lookahead)\n#modelsummary(models, coef_omit = \"^(?!Vol)\", gof_omit = \".*\")\n\n# coef_omit: keep coefficients matching a substring\nmodelsummary(models, coef_omit = \"^(?!.*ei|.*pt)\", gof_omit = \".*\")\n\n \n\n \n \n\ntinytable_leo6hlsmpbh7w23dcxet\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\n\n\n\n \n\n# shape: multinomial model\nlibrary(nnet)\nmulti <- multinom(factor(cyl) ~ mpg + hp, data = mtcars, trace = FALSE) \n\n# shape: term names and group ids in rows, models in columns\nmodelsummary(multi, shape = response ~ model)\n\n \n\n \n \n\ntinytable_2x6f6mtmn6m96xomt61h\n\n\n \n\n \n response\n (1)\n \n\n\n(Intercept)\n 6\n 0.500 \n \n\n \n \n (41.760) \n \n\n \n 8\n 8.400 \n \n\n \n \n (0.502) \n \n\nmpg \n 6\n -83.069 \n \n\n \n \n (416.777)\n \n\n \n 8\n -120.167 \n \n\n \n \n (508.775)\n \n\nhp \n 6\n 16.230 \n \n\n \n \n (81.808) \n \n\n \n 8\n 20.307 \n \n\n \n \n (87.777) \n \n\nNum.Obs. \n \n 32 \n \n\nR2 \n \n 1.000 \n \n\nR2 Adj. \n \n 0.971 \n \n\nAIC \n \n 12.0 \n \n\nBIC \n \n 20.8 \n \n\nRMSE \n \n 0.00 \n \n\n\n\n\n \n\n# shape: term names and group ids in rows in a single column\nmodelsummary(multi, shape = term : response ~ model)\n\n \n\n \n \n\ntinytable_qp9b1b3zy0ngjz4s1ixu\n\n\n \n\n \n (1)\n \n\n\n(Intercept) 6\n 0.500 \n \n\n \n (41.760) \n \n\nmpg 6 \n -83.069 \n \n\n \n (416.777)\n \n\nhp 6 \n 16.230 \n \n\n \n (81.808) \n \n\n(Intercept) 8\n 8.400 \n \n\n \n (0.502) \n \n\nmpg 8 \n -120.167 \n \n\n \n (508.775)\n \n\nhp 8 \n 20.307 \n \n\n \n (87.777) \n \n\nNum.Obs. \n 32 \n \n\nR2 \n 1.000 \n \n\nR2 Adj. \n 0.971 \n \n\nAIC \n 12.0 \n \n\nBIC \n 20.8 \n \n\nRMSE \n 0.00 \n \n\n\n\n\n \n\n# shape: term names in rows and group ids in columns\nmodelsummary(multi, shape = term ~ response:model)\n\n \n\n \n \n\ntinytable_kkvdw7jviuquvn5wqnzs\n\n\n \n\n\n \n(1)\n\n\n \n 6\n 8\n \n\n\n\n(Intercept)\n 0.500 \n 8.400 \n \n\n \n (41.760) \n (0.502) \n \n\nmpg \n -83.069 \n -120.167 \n \n\n \n (416.777)\n (508.775)\n \n\nhp \n 16.230 \n 20.307 \n \n\n \n (81.808) \n (87.777) \n \n\nNum.Obs. \n 32 \n \n \n\nR2 \n 1.000 \n \n \n\nR2 Adj. \n 0.971 \n \n \n\nAIC \n 12.0 \n \n \n\nBIC \n 20.8 \n \n \n\nRMSE \n 0.00 \n \n \n\n\n\n\n \n\n# shape = \"rcollapse\"\npanels <- list(\n \"Panel A: MPG\" = list(\n \"A\" = lm(mpg ~ hp, data = mtcars),\n \"B\" = lm(mpg ~ hp + factor(gear), data = mtcars)),\n \"Panel B: Displacement\" = list(\n \"A\" = lm(disp ~ hp, data = mtcars),\n \"C\" = lm(disp ~ hp + factor(gear), data = mtcars))\n)\n\n# shape = \"cbind\"\nmodelsummary(panels, shape = \"cbind\")\n\n \n\n \n \n\ntinytable_i3nyohz4ryvw87xcdrvr\n\n\n \n\n\n \nPanel A: MPG\nPanel B: Displacement\n\n\n \n A\n B\n A \n C\n \n\n\n\n(Intercept) \n 30.099 \n 27.882 \n 20.992 \n 112.093 \n \n\n \n (1.634)\n (2.109)\n (32.607)\n (34.704)\n \n\nhp \n -0.068 \n -0.067 \n 1.430 \n 1.216 \n \n\n \n (0.010)\n (0.011)\n (0.202) \n (0.182) \n \n\nfactor(gear)4\n \n 2.635 \n \n -97.923 \n \n\n \n \n (1.552)\n \n (25.532)\n \n\nfactor(gear)5\n \n 6.575 \n \n -147.495\n \n\n \n \n (1.643)\n \n (27.030)\n \n\nNum.Obs. \n 32 \n 32 \n 32 \n 32 \n \n\nR2 \n 0.602 \n 0.753 \n 0.626 \n 0.842 \n \n\nR2 Adj. \n 0.589 \n 0.726 \n 0.613 \n 0.825 \n \n\nAIC \n 181.2 \n 170.0 \n 372.8 \n 349.3 \n \n\nBIC \n 185.6 \n 177.4 \n 377.2 \n 356.6 \n \n\nLog.Lik. \n -87.619\n -80.024\n -183.412\n -169.643\n \n\nF \n 45.460 \n 28.407 \n 50.128 \n 49.611 \n \n\nRMSE \n 3.74 \n 2.95 \n 74.64 \n 48.54 \n \n\n\n\n\n \n\nmodelsummary(\n panels,\n shape = \"rbind\",\n gof_map = c(\"nobs\", \"r.squared\"))\n\n \n\n \n \n\ntinytable_8g8cbr2e6rkzqw58oxza\n\n\n \n\n \n A\n B\n C\n \n\n\n(Intercept) \n 30.099 \n 27.882 \n \n \n\n \n (1.634) \n (2.109)\n \n \n\nhp \n -0.068 \n -0.067 \n \n \n\n \n (0.010) \n (0.011)\n \n \n\nfactor(gear)4\n \n 2.635 \n \n \n\n \n \n (1.552)\n \n \n\nfactor(gear)5\n \n 6.575 \n \n \n\n \n \n (1.643)\n \n \n\nNum.Obs. \n 32 \n 32 \n \n \n\nR2 \n 0.602 \n 0.753 \n \n \n\n(Intercept) \n 20.992 \n \n 112.093 \n \n\n \n (32.607)\n \n (34.704)\n \n\nhp \n 1.430 \n \n 1.216 \n \n\n \n (0.202) \n \n (0.182) \n \n\nfactor(gear)4\n \n \n -97.923 \n \n\n \n \n \n (25.532)\n \n\nfactor(gear)5\n \n \n -147.495\n \n\n \n \n \n (27.030)\n \n\nNum.Obs. \n 32 \n \n 32 \n \n\nR2 \n 0.626 \n \n 0.842 \n \n\n\n\n\n \n\n# title\nmodelsummary(models, title = 'This is the title')\n\n \n\n \n \n\ntinytable_4i850ve155sa8cck22rk\n\n\n \n\nThis is the title\n \n \n Bivariate\n Multivariate\n \n\n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# title with LaTeX label (for numbering and referencing)\nmodelsummary(models, title = 'This is the title \\\\label{tab:description}')\n\n \n\n \n \n\ntinytable_8m7o5gclykcsbtnqn7gh\n\n\n \n\nThis is the title \\label{tab:description}\n \n \n Bivariate\n Multivariate\n \n\n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# add_rows\nrows <- tibble::tribble(~term, ~Bivariate, ~Multivariate,\n 'Empty row', '-', '-',\n 'Another empty row', '?', '?')\nattr(rows, 'position') <- c(1, 3)\nmodelsummary(models, add_rows = rows)\n\n \n\n \n \n\ntinytable_u2tqoc5p422bx49w9j60\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\nEmpty row \n - \n - \n \n\n(Intercept) \n -6.188 \n 10.816 \n \n\nAnother empty row\n ? \n ? \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# notes\nmodelsummary(models, notes = list('A first note', 'A second note'))\n\n \n\n \n \n\ntinytable_0ghxu5xl138u2hrnedt4\n\n\n \n\n \n Bivariate\n Multivariate\n \n\nA first note\nA second note\n\n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nNum.Obs. \n 31 \n 31 \n \n\nR2 \n 0.270 \n 0.941 \n \n\nR2 Adj. \n 0.244 \n 0.937 \n \n\nAIC \n 154.1 \n 78.2 \n \n\nBIC \n 158.4 \n 84.0 \n \n\nLog.Lik. \n -74.061\n -35.116\n \n\nF \n 10.707 \n 222.471\n \n\nRMSE \n 2.64 \n 0.75 \n \n\n\n\n\n \n\n# gof_map: tribble\nlibrary(tibble)\ngm <- tribble(\n ~raw, ~clean, ~fmt,\n \"r.squared\", \"R Squared\", 5)\nmodelsummary(models, gof_map = gm)\n\n \n\n \n \n\ntinytable_3znxwmq3oulnxnzngn8k\n\n\n \n\n \n Bivariate\n Multivariate\n \n\n\n(Intercept)\n -6.188 \n 10.816 \n \n\n \n (5.960)\n (1.973)\n \n\nHeight \n 0.256 \n -0.045 \n \n\n \n (0.078)\n (0.028)\n \n\nVolume \n \n 0.195 \n \n\n \n \n (0.011)\n \n\nR Squared \n 0.26965\n 0.94080", + "crumbs": [ + "Get started", + "Functions", + "`modelsummary`" + ] + }, + { + "objectID": "man/datasummary_correlation_format.html", + "href": "man/datasummary_correlation_format.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Mostly for internal use, but can be useful when users supply a function to the method argument of datasummary_correlation.\n\ndatasummary_correlation_format(\n x,\n fmt,\n leading_zero = FALSE,\n diagonal = NULL,\n upper_triangle = NULL\n)\n\n\n\n\n\nx\n\n\nsquare numeric matrix\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\nleading_zero\n\n\nboolean. If FALSE, leading zeros are removed\n\n\n\n\ndiagonal\n\n\ncharacter or NULL. If character, all elements of the diagonal are replaced by the same character (e.g., \"1\").\n\n\n\n\nupper_triangle\n\n\ncharacter or NULL. If character, all elements of the upper triangle are replaced by the same character (e.g., \"\" or \".\").\n\n\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\ndat <- mtcars[, c(\"mpg\", \"hp\", \"disp\")]\n\ncor_fun <- function(x) {\n out <- cor(x, method = \"kendall\")\n datasummary_correlation_format(\n out,\n fmt = 2,\n upper_triangle = \"x\",\n diagonal = \".\")\n}\n\ndatasummary_correlation(dat, method = cor_fun)\n\n \n\n \n \n\ntinytable_jyfmr10er0pi83lzoint\n\n\n \n\n \n mpg\n hp\n disp\n \n\n\nmpg \n . \n x \n x\n \n\nhp \n -.74\n . \n x\n \n\ndisp\n -.77\n .67\n .", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`datasummary_correlation_format`" + ] + }, + { + "objectID": "man/datasummary_correlation_format.html#format-the-content-of-a-correlation-table", + "href": "man/datasummary_correlation_format.html#format-the-content-of-a-correlation-table", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Mostly for internal use, but can be useful when users supply a function to the method argument of datasummary_correlation.\n\ndatasummary_correlation_format(\n x,\n fmt,\n leading_zero = FALSE,\n diagonal = NULL,\n upper_triangle = NULL\n)\n\n\n\n\n\nx\n\n\nsquare numeric matrix\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\nleading_zero\n\n\nboolean. If FALSE, leading zeros are removed\n\n\n\n\ndiagonal\n\n\ncharacter or NULL. If character, all elements of the diagonal are replaced by the same character (e.g., \"1\").\n\n\n\n\nupper_triangle\n\n\ncharacter or NULL. If character, all elements of the upper triangle are replaced by the same character (e.g., \"\" or \".\").\n\n\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\ndat <- mtcars[, c(\"mpg\", \"hp\", \"disp\")]\n\ncor_fun <- function(x) {\n out <- cor(x, method = \"kendall\")\n datasummary_correlation_format(\n out,\n fmt = 2,\n upper_triangle = \"x\",\n diagonal = \".\")\n}\n\ndatasummary_correlation(dat, method = cor_fun)\n\n \n\n \n \n\ntinytable_jyfmr10er0pi83lzoint\n\n\n \n\n \n mpg\n hp\n disp\n \n\n\nmpg \n . \n x \n x\n \n\nhp \n -.74\n . \n x\n \n\ndisp\n -.77\n .67\n .", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`datasummary_correlation_format`" + ] + }, + { + "objectID": "NEWS.html", + "href": "NEWS.html", + "title": "News", + "section": "", + "text": "New features:\n\nmodelsummary() gets a gof_function argument which accepts functions to extract custom information from models.\n\ndatasummary_balance():\n\nformula can now include variables on the left-hand side to indicate the subset of columns to summarize: datasummary_balance(mpg + hp ~ am, data = mtcars) Thanks to @etiennebacher for feature request #751.\n\nBugs:\n\nescape argument not respected in datasummary_df(). Thanks to @adamaltmejd for report #740\ndatasummary_correlation() supports data.table. Thanks to volatilehead on Twitter for report #737.\nAccepts named estimate argument when using shape and statistics are horizontal. Thanks to @iago-pssjd for report #745.\nLabelled values but no label for variable broke datasummary(). Thanks to @marklhc for report #752.\ncoef_map does not work when there is a group. Thanks to @mccarthy-m-g for report #757.\n\n\n\n\nMAJOR BREAKING CHANGE: The default output format is now tinytable instead of kableExtra. Learn more about tinytable here:\nhttps://vincentarelbundock.github.io/tinytable/\nTo revert to the previous behavior persistently, users can call:\nlibrary(modelsummary) config_modelsummary(factory_default = “kableExtra”)\nOther breaking changes:\n\nThe statistic_override argument was replaced by vcov over 1 year ago, with appropriate deprecation warnings. It is now fully removed.\nThe group argument was replaced by shape several releases ago. It is now fully removed.\ndatasummary_skim()\n\nhistograms are only available with the tinytable backend. This allows a lot of code simplification and more customization.\nThe order of arguments type and output is switched for consistency with other functions.\nhistogram argument is deprecated.\n\n\nNew features:\n\ndatasummary_skim():\n\nNew type=\"all\" by default to display both numeric and categorical variables in a single table with distinct panels. This feature is only available with the tinytable backend (default).\nby argument allows summarizing numeric variables by group.\nfun_numeric argument accepts a list of functions to control the summary columns.\n\nmodelsummary():\n\nstatistic and estimate can be specified as named vectors to control the names of statistics when displayed in different columns using the shape argument. (Thanks to @mps9506 for bug report #722)\nmodelsummary(panels, shape = \"cbind\") automatically adds column-spanning labels when panels is a named nested list of models.\n\nconfig_modelsummary() gets a startup_message argument to silence the startup message persistently.\nImproved documentation and vignettes, providing clearer instructions and examples.\nUpdated tests and snapshots to ensure reliability and consistency across changes.\n\nBug fixes:\n\nFixed Issue #399: datasummary_balance() siunitx formatting.\nFixed Issue #782: Useless warning in some modelplot() calls. Thanks to @iago-pssjd for the report and @florence-laflamme for the fix.\nAddressed various bugs and made optimizations for better performance and user experience.\n\n\n\n\n\ntinytable supports histograms in datasummary_skim()\nconfig_modelsummary() supports tinytable factory.\n\n\n\n\n\nSupport the tinytable package as an output format (“factory”): https://vincentarelbundock.github.io/tinytable/\nQuarto: md output format is recognized.\noptions(modelsummary_factory_default) is respected, even in qmd->md documents.\n\nBugs:\n\nSome omitted coefficients with I() operator in formulas. Issue #693.\n\n\n\n\nMisc:\n\nDuplicate values in shape groups are removed automatically for cleaner labels.\n“Title” line no longer indented in markdown tables. Thanks to Ryan Briggs for report #671.\n\nBugs:\n\nSmall p values were not displayed properly in HTML output using kableExtra. Issue #669.\n\n\n\n\nNew:\n\nMinimal support for Typst output, with auto-detection in Quarto documents.\nstrip argument in dvnames.\ns.value statistic is now available whenever p.value is available. See Greenland (2019).\ndatasummary_skim() now includes histograms in gt tables.\n\nBugs:\n\nGOF term names get escaped in LaTeX. Thanks to @shreyasgm for reviving Issue #546.\nConflict with furrr generated errors for some models. Thanks to @sammo3182 for Issue #647.\n\n\n\n\nNew:\n\nfmt_sci() can now be used in the fmt argument for rounding with scientific notation.\n\nBugs:\n\nGroup separators respect add_rows with shape=\"rbind\". Thanks to @lrose1 for Report #626.\nBad column with horizontal models in shape and grouped estimates. Thanks to @iago-pssjd for Report #631.\ncoef_rename=TRUE bug with grouped estimates. Thanks to @iago-pssjd for Report #631.\nUpstream issue #881 in parameters meant that vcov was no longer used for confidence intervals.\n\n\n\n\n\nBuilt-in support for markdown tables.\nPackage no longer depends on kableExtra. Recommends an additional install for other formats.\nPersistent configuration of default output format: config_modelsummary(factory_default = \"gt\")\nshape = \"rcollapse\" and shape = \"rbind\"\nglance_custom() can drop GOF by assigning NA: https://stackoverflow.com/questions/75215355/assigning-different-coefficient-names-and-goodness-of-fit-statistics-to-differen\nWhen a statistic is not available, modelsummary prints an empty cell instead of returning an error.\n“\\label{tab:something}” works in title even when escape=TRUE\nMultiple fixest_multi objects supported.\noptions(modelsummary_future = FALSE) disables future parallelism.\n\nBug fixes:\n\nstatistic=NULL is now respected when shape=\"rbind\". Thanks to Panos Mavros for report #620.\nget_estimates() supports vcov string shortcuts and formulas. Thanks to @ethans-carl for report #605.\nQuarto and Rmarkdown documents include situnix in header automatically for decimal alignement with align=\"ddd\"\nescape is now respected by modelsummary with shape=\"rbind\". Thanks to @chickymonkeys for report #622.\n\n\n\n\nBreaking change:\n\nThe default column label style in modelsummary() has changed from “Model 1” to “(1)”. The benefits are: labels are no longer in English by default; use less horizontal space; eliminate the “Model” redundancy. Unfortunately, this could break code in some edge cases where users rely on column names to manipulate tables. The old behavior can be restored by calling: options(modelsummary_model_labels=\"model\")\n\nNew features:\n\nshape=\"rbind\" to stack multiple regression tables and create “panels” with labelled groups of models.\nfmt: new helper functions for different formatting styles\n\nfmt = fmt_decimal(2): decimal digits\nfmt = fmt_decimal(digits = 2, pdigits = 4): decimal digits with p value-specific setting\nfmt = fmt_sprintf(\"%.3f\"): sprintf() decimal\nfmt = fmt_sprintf(\"%.3e\"): sprintf() scientific\nfmt = fmt_significant(3): significant digits\nfmt = fmt_statistic(\"estimate\" = 2, \"std.error\" = 3): statistic-specific formatting\nfmt = fmt_term(\"(Intercept)\" = 2, \"hp\" = 3): term-specific formatting\nfmt = fmt_identity(): raw values\n\nNew styles for default column labels in modelsummary, such as Roman Numerals or letters in parentheses.\n\nSet the style with a global option: options(modelsummary_model_labels = \"roman\")\nSupported styles: “model”, “arabic”, “letters”, “roman”, “(arabic)”, “(letters)”, “(roman)””\n\nmodelplot(draw = FALSE) now returns a p.value column. This allows conditional aesthetics (see the modelplot vignette).\nBetter integration with the marginaleffects package.\n\nBugs:\n\nSome fixest models returns useless “group.x” and “group.y” columns. Isse #591. Thanks to Adam Altmejd for the report.\n\n\n\n\nBreaking change:\n\nWith the shape and output=\"dataframe\" arguments, there always used to be a group column. Now, this column has the same name as the variable in the shape formula (“response”, “component”, etc.).\n\nNew features:\n\nshape can include multiple groups.\ncoef_rename can be an unnamed vector of length equal to the number of terms in the final table, obtained after coef_map and coef_omit are applied and models are merged.\ncoef_omit accepts numeric indices. Positive values: coefficients to omit. Negative values: coefficients to keep.\ndatasummary_skim: Increased maximum number of variables to 250.\nQuarto notebooks compile to Word and Markdown automatically.\n\nBug fixes:\n\nOrder of notes preserved in some output format (Issue #577)\n\n\n\n\nBreaking change:\n\nRequires siunitx version 3.0.25 LaTeX package.\nThe title argument now respects the escape argument for all kableExtra output formats. This can break tables in which users manually escaped titles.\n\nNew features:\n\n“d” is accepted for decimal-alignment in the align argument for all output formats. modelsummary(mod, align = \"ld\")\nNew update_modelsummary() function makes it easy to install the dev versions of modelsummary and its dependencies (mostly useful for Vincent and people who report bugs).\nRounding: display at least one significant digit by default.\nAutomatic renaming of haven labels in modelsummary(), datasummary(), datasummary_skim()\nAllow output = \"filename.csv\"\nAllow output = \"filename.xlsx\"\nadd_columns argument supported in modelsummary()\ndatasummary_balance supports the stars argument.\nAllow stars and confidence intervals with align = \"d\" column.\n\nBug fixes:\n\nIn some locales, the HTML minus sign created problems in the output. We only use it in “known” locales.\nMany minor bug fixes\n\n\n\n\n\nMinor release to fix CRAN failure\n\n\n\n\n\nshape argument accepts interactions with the colon “:” character. This combines two columns into one, which can be useful to display terms and group names in a single column.\nParallelization using parallel::mclapply. See ?modelsummary\nmodelsummary no longer computes confidence intervals when not necessary, which can save some time. Also see: conf_level=NULL\nAdded log likelihood to GOF for lm and glm models.\nRemoved extraneous warnings\nBug fixes\n\n\n\n\nThis first major release accompanies the publication of an article in the Journal of Statistical Software:\nArel-Bundock, Vincent (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. doi:10.18637/jss.v103.i01 https://doi.org/10.18637/jss.v103.i01.’\nIf you like modelsummary, please cite the JSS article and tell your friends about it.\nMinor changes:\n\ngof_map=\"all\" includes all available statistics. gof_map=\"none\" excludes all statistics.\nBug fixes\n\n\n\n\n\nBetter printout for term names in mixed-effects models\n{brms} and {stanreg} models now extracted with diagnostic=NULL and test=NULL by default for speed.\n\n\n\n\nBreaking changes:\n\nmodelsummary_wide is no longer available. Use the shape argument of modelsummary instead.\nmodelsummary now uses the easystats packages (performance and parameters) to extract estimates and goodness-of-fit statistics instead of broom. This can be reverted by setting a global option: options(modelsummary_get=\"broom\"). This change aims to (1) increase consistency across models, (2) improve the developers’ ability to push bug fixes upstream when necessary, and (3) improve support for mixed effects, bayesian, and GAM models. The two main drawbacks are: (a) The set of printed statistics may be slightly different from previous versions of modelsummary (b) The group identifiers used in the shape formula will also be different for certain models (e.g., in nnet::multinom, y.level becomes response).\n\nNew features:\n\nThe shape argument accepts a formula and can reshape information in myriad ways. Deprecates the group argument. Examples:\n\n~ statistic: statistics are shown horizontally in distinct columns.\nmodel ~ term: models in rows and terms in columns.\nterm + y.level + statistic ~ model: grouped coefficients for multivariate outcome in nnet::multinom\ny.level ~ model: partial match is the same as the previous formula\n\nFormat distinct statistics differently by passing a named list to fmt:\n\nmodelsummary(mod, fmt = list(estimate = 2, std.error = 1, rmse = 4))\n\nUse glue to apply functions to numeric values by setting fmt = NULL. Example:\n\nmodelsummary(model, fmt = NULL, estimate = \"{log(estimate)}\")\n\nUpdate for breaking changes after fixest 0.10.4\n\nBug fixes:\n\ngroup_map rename issue\nResidual standard error mistakenly labelled “RMSE” in lm models.\ndatasummary_skim output to jpg should now works\nescape fixes\n\n\n\n\n\nNew exponentiate argument for modelsummary() and modelplot()\ngof_map accepts a vector such as c(\"rmse\", \"nobs\", \"r.squared\")\nDrop rlang dependency\nBug fixes\n\n\n\n\ndatasummary_balance:\n\nAccepts ~ 1 as a formula to summarize all data.\n\nMisc:\n\ndocumentation improvements\nRMSE included by default in models of class lm\n\n\n\n\nmodelsummary:\n\nvcov strings like HC1 and Robust are now case-insensitive\ngof_map now accepts a data.frame or tibble with a fmt list-column which includes functions (see Examples in docs)\nR2 is no longer computed by default for bayesian and mixed effects models. An informative one-time warning is printed about the metrics argument.\n\ndatasummary_skim:\n\nHistograms now work in Jupyter\nBugfix: harmless error message is no longer printed\n\nkableExtra factory:\n\nThe col.names argument can now be passed to kableExtra::kbl through the … ellipsis.\n\nMisc:\n\nMany small improvements to the vignettes and docs\noutput = \"github_document\" is now supported\n\n\n\n\n\nBug fix: siunitx and rounding NA\n\n\n\n\nmodelsummary:\n\nF statistic takes into account vcov argument\nSupport group = group ~ model + term\n\ndatasummary_balance:\n\nWeighted means and standard deviations are now supported. Counts and percentages are not, but raise a warning.\n\nMisc:\n\nBugfix: rounding in LaTeX w/ siunitx and NaN entries.\noutput=‘jupyter’ no longer prints an extraneous TRUE to the notebook\n\n\n\n\nmodelsummary:\n\nImproved vcov argument handling for fixest models (#357 by @grantmcdermott)\nFix display of fixest::i() variables and interactions (#361 by @grantmcdermott)\nConsistent display of clustered SEs (#356, #363 and #366 by @grantmcdermott)\n\ndatasummary_correlation:\n\nadd_rows and add_columns arguments are now available here.\n\nMisc:\n\nGlobal options for output factories are renamed: modelsummary_factory_default, modelsummary_factory_html, etc.\nHot fix for change in R-devel behavior or intersect\n\nBug fixes:\n\ndatasummary_balance: escape variable names when escape=TRUE\nBlogdown LaTeX dependency bug when output is HTML\n\n\n\n\nBreaking change:\n\nSupport for dcolumn for dot-aligned columns is deprecated. Use “d” in the align argument instead.\n\nOther changes:\n\nLaTeX output: Numeric entries are wrapped in the \\num{} function from the siunitx package by default. This produces much nicer formatting. This can be disabled with a global option. See ?modelsummary\nThe align argument accepts a “d” column for dot-alignment using the siunitx LaTeX package: align=\"ldd\".\nHTML tables display proper minus signs.\nNew escape argument in most table-building functions.\nLaTeX output accepts the threeparttable=TRUE argument through ...\nNo more dependency on tidyr\n\nmodelsummary:\n\ngroup: The order of terms in the formula determines the order of rows/columns\n\nmodelsummary_wide:\n\nNote: This function will eventually be deprecated\nBugfix with statistic=NULL.\n\nmodelplot:\n\nPreserves order of models in the user-supplied list\n\ndatasummary_crosstab:\n\nstatistic=NULL produces a very basic crosstab\n\ndatasummary_crosstab:\n\nDefault alignment “lrrrrr” consistent with other datasummary_* functions\n\n\n\n\nmodelsummary:\n\nDisable stars footnote with options(\"modelsummary_stars_note\" = FALSE)\nlongtable=TRUE works for LaTeX output\nInteractions with “:” are no longer converted to “x” when coef_map or coef_rename are used.\ngroup = model ~ term + group is now supported.\n\ndatasummary_skim:\n\ndatasummary_skim(\"categorical\") keeps NA by default. Users can convert variables to factors before calling datasummary_skim to exclude NA.\n\nOther:\n\nImproved warnings for bad calls: modelsummary(model1, model2)\ngt titles use the new caption argument in the gt 0.3.0 function\nBug fix: Overaggressive tests for glue strings prevented functions inside {}\n\n\n\n\nBreaking change:\n\nThe default significance markers stars=TRUE have been updated to be consistent with the default output from base R (e.g., in summary.lm). The new significance thresholds are: “+” p < 0.1, “” p < 0.05, ”” p < 0.01, ”” p < 0.001\n\ndatasummary_crosstab:\n\nNew function to produce cross-tabulations\n\ndatasummary:\n\nN is smart enough to return either the number of elements in a subset or the number of non-missing observations in a variable\n\ndatasummary_balance:\n\nKeeps NAs in factor variables by default. Users can convert their variables with the factor() function to omit NAs automatically.\n\nmodelsummary:\n\nthemes can be set using global options (experimental)\nnew vcov options: “bootstrap”, “HAC”, “NeweyWest”, “Andrews”, “panel-corrected”, “weave”, “outer-product”\nA valid get_gof (glance) is now optional.\n… is pushed through to sandwich, which allows things like: modelsummary(model, vcov = \"bootstrap\", R = 1000, cluster = \"firm\")\n\nOther:\n\nJupyter notebook support via output=\"jupyter\"\nBug fixes\n\n\n\n\nmodelsummary:\n\nnew arguments for modelsummary: group and group_map for grouped parameters (e.g., outcome levels in multinomial logit or components of gamlss model).\ndvnames() makes it easy to get dependent variable column titles (thanks to @NickCH-K)\noutput=\"modelsummary_list\" to save a lightweight list-based representation of the table which can be saved and fed to modelsummary once more to get a full table.\nvcov adds a row to note the type of standard errors.\nmodelsummary accepts a single model with multiple vcovs.\nget_gof forwards … to model_performance\ncoef_map accepts unnamed vectors for easy subsetting\nfixest::fixest_multi support\noptions(modelsummary_get) to set the order of extraction functions to use under the hood (broom vs. easystats vs. all)\nmetrics argument of performance::model_performance is available via modelsummary’s … ellipsis to limit the GOF statistics in Bayesian models.\nusers can omit the stars legend note by using glue strings: estimate=\"{estimate}{stars}\"\noutput=“html” can use gt by setting options(modelsummary_factory_html=\"gt\")\n\ndatasummary_correlation:\n\npasses ... forward\nnew function: datasummary_correlation_format\ndatasummary_correlation’s method argument accepts functions and “pearspear” (thanks to @joachim-gassen)\n\ndatasummary:\n\ndatasummary functions and rounding accept …, big.mark, etc.\n\ndatasummary_skim:\n\nnow works with haven_labeled numeric\nfaster tables with bayesian models.\n\nBug fixes and lints\n\n\n\n\nnew output format: latex_tabular\ntidy_custom allows partial term matches\nmodelsummary(coef_rename) accepts functions\nnew function coef_rename for use in modelsummary(coef_rename=coef_rename)\nmodelplot accepts add_rows to add reference categories\ninformative error message when estimate or statistic is not available\nbug fixes\n\n\n\n\n\nstatistic_override becomes vcov\nvcov accepts shortcuts: “robust”, “stata”, “HC0”, etc.\nvcov accepts formulas for clustered SEs: ~group\nmodelsummary_wide has a new “stacking” argument\nhtml horizontal rule to separate estimates form gof\ngof_map accepts list of lists. only needs 3 columns.\nsupport officedown Rmd\nestimate accepts a vector for per model estimates\noptions(modelsummary_default) can be markdown, html, latex\nbug: passing arguments through …\nbug: stars and rounding\n\n\n\n\n\nglue format for estimate and statistic\neasystats support for model info extraction\ndeprecate statistic_vertical\ndeprecate extract_models. Use modelsummary(output=“dataframe”) instead.\nmodelplot pushes … through to modelsummary(output=“dataframe”)\ndatasummary_skim(type=“dataset”)\ngof_map omits by default\ndatasummary_balance uses row percentages\nstatistic_override does not require a list\nstatistic_override accepts a single model\nN function for well formatted N in datasummary\nBug fixes\n\n\n\n\n\nnew function: modelsummary_wide\ncoef_omit and gof_omit use grepl(perl=TRUE)\nfmt accepts integer, string or function and respects options(OutDec=“,”)\nalign argument for modelsummary\nalign is more liberal to accept dcolumn alignment\nglance_custom methods for lfe and fixest\nbug fixes\n\n\n\n\n\nnew argument: coef_rename\nnew function: datasummary_df\npreserve term order in modelsummary\nrefactor datasummary_balance\ndatasummary_skim uses svg histograms instead of unicode\nremoved 5 dependencies\npass … to kableExtra::kbl for more customization\ntest improvements\ninternal code style\nbug fixes\n\n\n\n\n\nbug fixes\n\n\n\n\n\ndefault HTML output factory is now kableExtra\ninteraction “:” gsubbed by “0d7”\ndependencies: removed 1 depends, 3 imports, and 3 suggests\nword_document knitr works out-of-the-box\nbug fixes\n\n\n\n\n\nglance_custom.fixest ships with modelsummary\n\n\n\n\n\ndatasummary\ndatasummary_skim\ndatasummary_balance\ndatasummary_correlation\nmodelplot\nallow duplicate model names\nbug: can’t use coef_map with multiple statistics (thanks @sbw78)\nbug: wrong number of stars w/ statistic=‘p.value’ (thanks @torfason)\noutput=‘data.frame’. extract is no longer documented.\n\n\n\n\n\nadd_rows now accepts a data.frame with “position” and “section” columns\nadd_rows_location is deprecated\nbug in sanity_output prevented overwriting files\n\n\n\n\n\nhuxtable support\nflextable support\nestimate argument\nfixest tidiers\nwebsite and vignette improvements\ngof_map additions\nglance_custom\ntidy_custom\n\n\n\n\n\nOut-of-the-box Rmarkdown compilation to HTML, PDF, RTF\nkableExtra output format for LaTeX and Markdown\nSupport for threeparttable, colors, and many other LaTeX options\nDeprecated arguments: filename, subtitle\nDeprecated functions: clean_latex, knit_latex\npkgdown website and doc improvements\nmitools tidiers\nNew tests\n\n\n\n\n\nConvenience function to render markdown in row/column labels\nbug: breakage when all GOF were omitted\nClean up manual with @keywords internal\nbug: tidyr import\n\n\n\n\n\ngt is now available on CRAN\nnew latex_env argument for knit_latex and clean_latex\nbug when all gof omitted\nbug in statistic_override with functions\nbug caused by upstream changes in tab_style\nbug caused by upstream changes in filename=‘rtf’\nAllow multiple rows of uncertainty estimates per coefficient\nPreserve add_rows order\nDisplay uncertainty estimates next to the coefficient with statistic_vertical = FALSE\nBetter clean_latex function\nCan display R2 and confidence intervals for mice-imputed lm-models\nInternal functions have @keywords internal to avoid inclusion in docs\nStatistic override accepts pre-formatted character vectors\n\n\n\n\n\nInitial release (gt still needs to be installed from github)", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#development", + "href": "NEWS.html#development", + "title": "News", + "section": "", + "text": "New features:\n\nmodelsummary() gets a gof_function argument which accepts functions to extract custom information from models.\n\ndatasummary_balance():\n\nformula can now include variables on the left-hand side to indicate the subset of columns to summarize: datasummary_balance(mpg + hp ~ am, data = mtcars) Thanks to @etiennebacher for feature request #751.\n\nBugs:\n\nescape argument not respected in datasummary_df(). Thanks to @adamaltmejd for report #740\ndatasummary_correlation() supports data.table. Thanks to volatilehead on Twitter for report #737.\nAccepts named estimate argument when using shape and statistics are horizontal. Thanks to @iago-pssjd for report #745.\nLabelled values but no label for variable broke datasummary(). Thanks to @marklhc for report #752.\ncoef_map does not work when there is a group. Thanks to @mccarthy-m-g for report #757.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section", + "href": "NEWS.html#section", + "title": "News", + "section": "", + "text": "MAJOR BREAKING CHANGE: The default output format is now tinytable instead of kableExtra. Learn more about tinytable here:\nhttps://vincentarelbundock.github.io/tinytable/\nTo revert to the previous behavior persistently, users can call:\nlibrary(modelsummary) config_modelsummary(factory_default = “kableExtra”)\nOther breaking changes:\n\nThe statistic_override argument was replaced by vcov over 1 year ago, with appropriate deprecation warnings. It is now fully removed.\nThe group argument was replaced by shape several releases ago. It is now fully removed.\ndatasummary_skim()\n\nhistograms are only available with the tinytable backend. This allows a lot of code simplification and more customization.\nThe order of arguments type and output is switched for consistency with other functions.\nhistogram argument is deprecated.\n\n\nNew features:\n\ndatasummary_skim():\n\nNew type=\"all\" by default to display both numeric and categorical variables in a single table with distinct panels. This feature is only available with the tinytable backend (default).\nby argument allows summarizing numeric variables by group.\nfun_numeric argument accepts a list of functions to control the summary columns.\n\nmodelsummary():\n\nstatistic and estimate can be specified as named vectors to control the names of statistics when displayed in different columns using the shape argument. (Thanks to @mps9506 for bug report #722)\nmodelsummary(panels, shape = \"cbind\") automatically adds column-spanning labels when panels is a named nested list of models.\n\nconfig_modelsummary() gets a startup_message argument to silence the startup message persistently.\nImproved documentation and vignettes, providing clearer instructions and examples.\nUpdated tests and snapshots to ensure reliability and consistency across changes.\n\nBug fixes:\n\nFixed Issue #399: datasummary_balance() siunitx formatting.\nFixed Issue #782: Useless warning in some modelplot() calls. Thanks to @iago-pssjd for the report and @florence-laflamme for the fix.\nAddressed various bugs and made optimizations for better performance and user experience.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-1", + "href": "NEWS.html#section-1", + "title": "News", + "section": "", + "text": "tinytable supports histograms in datasummary_skim()\nconfig_modelsummary() supports tinytable factory.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-2", + "href": "NEWS.html#section-2", + "title": "News", + "section": "", + "text": "Support the tinytable package as an output format (“factory”): https://vincentarelbundock.github.io/tinytable/\nQuarto: md output format is recognized.\noptions(modelsummary_factory_default) is respected, even in qmd->md documents.\n\nBugs:\n\nSome omitted coefficients with I() operator in formulas. Issue #693.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-3", + "href": "NEWS.html#section-3", + "title": "News", + "section": "", + "text": "Misc:\n\nDuplicate values in shape groups are removed automatically for cleaner labels.\n“Title” line no longer indented in markdown tables. Thanks to Ryan Briggs for report #671.\n\nBugs:\n\nSmall p values were not displayed properly in HTML output using kableExtra. Issue #669.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-4", + "href": "NEWS.html#section-4", + "title": "News", + "section": "", + "text": "New:\n\nMinimal support for Typst output, with auto-detection in Quarto documents.\nstrip argument in dvnames.\ns.value statistic is now available whenever p.value is available. See Greenland (2019).\ndatasummary_skim() now includes histograms in gt tables.\n\nBugs:\n\nGOF term names get escaped in LaTeX. Thanks to @shreyasgm for reviving Issue #546.\nConflict with furrr generated errors for some models. Thanks to @sammo3182 for Issue #647.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-5", + "href": "NEWS.html#section-5", + "title": "News", + "section": "", + "text": "New:\n\nfmt_sci() can now be used in the fmt argument for rounding with scientific notation.\n\nBugs:\n\nGroup separators respect add_rows with shape=\"rbind\". Thanks to @lrose1 for Report #626.\nBad column with horizontal models in shape and grouped estimates. Thanks to @iago-pssjd for Report #631.\ncoef_rename=TRUE bug with grouped estimates. Thanks to @iago-pssjd for Report #631.\nUpstream issue #881 in parameters meant that vcov was no longer used for confidence intervals.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-6", + "href": "NEWS.html#section-6", + "title": "News", + "section": "", + "text": "Built-in support for markdown tables.\nPackage no longer depends on kableExtra. Recommends an additional install for other formats.\nPersistent configuration of default output format: config_modelsummary(factory_default = \"gt\")\nshape = \"rcollapse\" and shape = \"rbind\"\nglance_custom() can drop GOF by assigning NA: https://stackoverflow.com/questions/75215355/assigning-different-coefficient-names-and-goodness-of-fit-statistics-to-differen\nWhen a statistic is not available, modelsummary prints an empty cell instead of returning an error.\n“\\label{tab:something}” works in title even when escape=TRUE\nMultiple fixest_multi objects supported.\noptions(modelsummary_future = FALSE) disables future parallelism.\n\nBug fixes:\n\nstatistic=NULL is now respected when shape=\"rbind\". Thanks to Panos Mavros for report #620.\nget_estimates() supports vcov string shortcuts and formulas. Thanks to @ethans-carl for report #605.\nQuarto and Rmarkdown documents include situnix in header automatically for decimal alignement with align=\"ddd\"\nescape is now respected by modelsummary with shape=\"rbind\". Thanks to @chickymonkeys for report #622.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-7", + "href": "NEWS.html#section-7", + "title": "News", + "section": "", + "text": "Breaking change:\n\nThe default column label style in modelsummary() has changed from “Model 1” to “(1)”. The benefits are: labels are no longer in English by default; use less horizontal space; eliminate the “Model” redundancy. Unfortunately, this could break code in some edge cases where users rely on column names to manipulate tables. The old behavior can be restored by calling: options(modelsummary_model_labels=\"model\")\n\nNew features:\n\nshape=\"rbind\" to stack multiple regression tables and create “panels” with labelled groups of models.\nfmt: new helper functions for different formatting styles\n\nfmt = fmt_decimal(2): decimal digits\nfmt = fmt_decimal(digits = 2, pdigits = 4): decimal digits with p value-specific setting\nfmt = fmt_sprintf(\"%.3f\"): sprintf() decimal\nfmt = fmt_sprintf(\"%.3e\"): sprintf() scientific\nfmt = fmt_significant(3): significant digits\nfmt = fmt_statistic(\"estimate\" = 2, \"std.error\" = 3): statistic-specific formatting\nfmt = fmt_term(\"(Intercept)\" = 2, \"hp\" = 3): term-specific formatting\nfmt = fmt_identity(): raw values\n\nNew styles for default column labels in modelsummary, such as Roman Numerals or letters in parentheses.\n\nSet the style with a global option: options(modelsummary_model_labels = \"roman\")\nSupported styles: “model”, “arabic”, “letters”, “roman”, “(arabic)”, “(letters)”, “(roman)””\n\nmodelplot(draw = FALSE) now returns a p.value column. This allows conditional aesthetics (see the modelplot vignette).\nBetter integration with the marginaleffects package.\n\nBugs:\n\nSome fixest models returns useless “group.x” and “group.y” columns. Isse #591. Thanks to Adam Altmejd for the report.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-8", + "href": "NEWS.html#section-8", + "title": "News", + "section": "", + "text": "Breaking change:\n\nWith the shape and output=\"dataframe\" arguments, there always used to be a group column. Now, this column has the same name as the variable in the shape formula (“response”, “component”, etc.).\n\nNew features:\n\nshape can include multiple groups.\ncoef_rename can be an unnamed vector of length equal to the number of terms in the final table, obtained after coef_map and coef_omit are applied and models are merged.\ncoef_omit accepts numeric indices. Positive values: coefficients to omit. Negative values: coefficients to keep.\ndatasummary_skim: Increased maximum number of variables to 250.\nQuarto notebooks compile to Word and Markdown automatically.\n\nBug fixes:\n\nOrder of notes preserved in some output format (Issue #577)", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-9", + "href": "NEWS.html#section-9", + "title": "News", + "section": "", + "text": "Breaking change:\n\nRequires siunitx version 3.0.25 LaTeX package.\nThe title argument now respects the escape argument for all kableExtra output formats. This can break tables in which users manually escaped titles.\n\nNew features:\n\n“d” is accepted for decimal-alignment in the align argument for all output formats. modelsummary(mod, align = \"ld\")\nNew update_modelsummary() function makes it easy to install the dev versions of modelsummary and its dependencies (mostly useful for Vincent and people who report bugs).\nRounding: display at least one significant digit by default.\nAutomatic renaming of haven labels in modelsummary(), datasummary(), datasummary_skim()\nAllow output = \"filename.csv\"\nAllow output = \"filename.xlsx\"\nadd_columns argument supported in modelsummary()\ndatasummary_balance supports the stars argument.\nAllow stars and confidence intervals with align = \"d\" column.\n\nBug fixes:\n\nIn some locales, the HTML minus sign created problems in the output. We only use it in “known” locales.\nMany minor bug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-10", + "href": "NEWS.html#section-10", + "title": "News", + "section": "", + "text": "Minor release to fix CRAN failure", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-11", + "href": "NEWS.html#section-11", + "title": "News", + "section": "", + "text": "shape argument accepts interactions with the colon “:” character. This combines two columns into one, which can be useful to display terms and group names in a single column.\nParallelization using parallel::mclapply. See ?modelsummary\nmodelsummary no longer computes confidence intervals when not necessary, which can save some time. Also see: conf_level=NULL\nAdded log likelihood to GOF for lm and glm models.\nRemoved extraneous warnings\nBug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-12", + "href": "NEWS.html#section-12", + "title": "News", + "section": "", + "text": "This first major release accompanies the publication of an article in the Journal of Statistical Software:\nArel-Bundock, Vincent (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. doi:10.18637/jss.v103.i01 https://doi.org/10.18637/jss.v103.i01.’\nIf you like modelsummary, please cite the JSS article and tell your friends about it.\nMinor changes:\n\ngof_map=\"all\" includes all available statistics. gof_map=\"none\" excludes all statistics.\nBug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-13", + "href": "NEWS.html#section-13", + "title": "News", + "section": "", + "text": "Better printout for term names in mixed-effects models\n{brms} and {stanreg} models now extracted with diagnostic=NULL and test=NULL by default for speed.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-14", + "href": "NEWS.html#section-14", + "title": "News", + "section": "", + "text": "Breaking changes:\n\nmodelsummary_wide is no longer available. Use the shape argument of modelsummary instead.\nmodelsummary now uses the easystats packages (performance and parameters) to extract estimates and goodness-of-fit statistics instead of broom. This can be reverted by setting a global option: options(modelsummary_get=\"broom\"). This change aims to (1) increase consistency across models, (2) improve the developers’ ability to push bug fixes upstream when necessary, and (3) improve support for mixed effects, bayesian, and GAM models. The two main drawbacks are: (a) The set of printed statistics may be slightly different from previous versions of modelsummary (b) The group identifiers used in the shape formula will also be different for certain models (e.g., in nnet::multinom, y.level becomes response).\n\nNew features:\n\nThe shape argument accepts a formula and can reshape information in myriad ways. Deprecates the group argument. Examples:\n\n~ statistic: statistics are shown horizontally in distinct columns.\nmodel ~ term: models in rows and terms in columns.\nterm + y.level + statistic ~ model: grouped coefficients for multivariate outcome in nnet::multinom\ny.level ~ model: partial match is the same as the previous formula\n\nFormat distinct statistics differently by passing a named list to fmt:\n\nmodelsummary(mod, fmt = list(estimate = 2, std.error = 1, rmse = 4))\n\nUse glue to apply functions to numeric values by setting fmt = NULL. Example:\n\nmodelsummary(model, fmt = NULL, estimate = \"{log(estimate)}\")\n\nUpdate for breaking changes after fixest 0.10.4\n\nBug fixes:\n\ngroup_map rename issue\nResidual standard error mistakenly labelled “RMSE” in lm models.\ndatasummary_skim output to jpg should now works\nescape fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-15", + "href": "NEWS.html#section-15", + "title": "News", + "section": "", + "text": "New exponentiate argument for modelsummary() and modelplot()\ngof_map accepts a vector such as c(\"rmse\", \"nobs\", \"r.squared\")\nDrop rlang dependency\nBug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-16", + "href": "NEWS.html#section-16", + "title": "News", + "section": "", + "text": "datasummary_balance:\n\nAccepts ~ 1 as a formula to summarize all data.\n\nMisc:\n\ndocumentation improvements\nRMSE included by default in models of class lm", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-17", + "href": "NEWS.html#section-17", + "title": "News", + "section": "", + "text": "modelsummary:\n\nvcov strings like HC1 and Robust are now case-insensitive\ngof_map now accepts a data.frame or tibble with a fmt list-column which includes functions (see Examples in docs)\nR2 is no longer computed by default for bayesian and mixed effects models. An informative one-time warning is printed about the metrics argument.\n\ndatasummary_skim:\n\nHistograms now work in Jupyter\nBugfix: harmless error message is no longer printed\n\nkableExtra factory:\n\nThe col.names argument can now be passed to kableExtra::kbl through the … ellipsis.\n\nMisc:\n\nMany small improvements to the vignettes and docs\noutput = \"github_document\" is now supported", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-18", + "href": "NEWS.html#section-18", + "title": "News", + "section": "", + "text": "Bug fix: siunitx and rounding NA", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-19", + "href": "NEWS.html#section-19", + "title": "News", + "section": "", + "text": "modelsummary:\n\nF statistic takes into account vcov argument\nSupport group = group ~ model + term\n\ndatasummary_balance:\n\nWeighted means and standard deviations are now supported. Counts and percentages are not, but raise a warning.\n\nMisc:\n\nBugfix: rounding in LaTeX w/ siunitx and NaN entries.\noutput=‘jupyter’ no longer prints an extraneous TRUE to the notebook", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-20", + "href": "NEWS.html#section-20", + "title": "News", + "section": "", + "text": "modelsummary:\n\nImproved vcov argument handling for fixest models (#357 by @grantmcdermott)\nFix display of fixest::i() variables and interactions (#361 by @grantmcdermott)\nConsistent display of clustered SEs (#356, #363 and #366 by @grantmcdermott)\n\ndatasummary_correlation:\n\nadd_rows and add_columns arguments are now available here.\n\nMisc:\n\nGlobal options for output factories are renamed: modelsummary_factory_default, modelsummary_factory_html, etc.\nHot fix for change in R-devel behavior or intersect\n\nBug fixes:\n\ndatasummary_balance: escape variable names when escape=TRUE\nBlogdown LaTeX dependency bug when output is HTML", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-21", + "href": "NEWS.html#section-21", + "title": "News", + "section": "", + "text": "Breaking change:\n\nSupport for dcolumn for dot-aligned columns is deprecated. Use “d” in the align argument instead.\n\nOther changes:\n\nLaTeX output: Numeric entries are wrapped in the \\num{} function from the siunitx package by default. This produces much nicer formatting. This can be disabled with a global option. See ?modelsummary\nThe align argument accepts a “d” column for dot-alignment using the siunitx LaTeX package: align=\"ldd\".\nHTML tables display proper minus signs.\nNew escape argument in most table-building functions.\nLaTeX output accepts the threeparttable=TRUE argument through ...\nNo more dependency on tidyr\n\nmodelsummary:\n\ngroup: The order of terms in the formula determines the order of rows/columns\n\nmodelsummary_wide:\n\nNote: This function will eventually be deprecated\nBugfix with statistic=NULL.\n\nmodelplot:\n\nPreserves order of models in the user-supplied list\n\ndatasummary_crosstab:\n\nstatistic=NULL produces a very basic crosstab\n\ndatasummary_crosstab:\n\nDefault alignment “lrrrrr” consistent with other datasummary_* functions", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-22", + "href": "NEWS.html#section-22", + "title": "News", + "section": "", + "text": "modelsummary:\n\nDisable stars footnote with options(\"modelsummary_stars_note\" = FALSE)\nlongtable=TRUE works for LaTeX output\nInteractions with “:” are no longer converted to “x” when coef_map or coef_rename are used.\ngroup = model ~ term + group is now supported.\n\ndatasummary_skim:\n\ndatasummary_skim(\"categorical\") keeps NA by default. Users can convert variables to factors before calling datasummary_skim to exclude NA.\n\nOther:\n\nImproved warnings for bad calls: modelsummary(model1, model2)\ngt titles use the new caption argument in the gt 0.3.0 function\nBug fix: Overaggressive tests for glue strings prevented functions inside {}", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-23", + "href": "NEWS.html#section-23", + "title": "News", + "section": "", + "text": "Breaking change:\n\nThe default significance markers stars=TRUE have been updated to be consistent with the default output from base R (e.g., in summary.lm). The new significance thresholds are: “+” p < 0.1, “” p < 0.05, ”” p < 0.01, ”” p < 0.001\n\ndatasummary_crosstab:\n\nNew function to produce cross-tabulations\n\ndatasummary:\n\nN is smart enough to return either the number of elements in a subset or the number of non-missing observations in a variable\n\ndatasummary_balance:\n\nKeeps NAs in factor variables by default. Users can convert their variables with the factor() function to omit NAs automatically.\n\nmodelsummary:\n\nthemes can be set using global options (experimental)\nnew vcov options: “bootstrap”, “HAC”, “NeweyWest”, “Andrews”, “panel-corrected”, “weave”, “outer-product”\nA valid get_gof (glance) is now optional.\n… is pushed through to sandwich, which allows things like: modelsummary(model, vcov = \"bootstrap\", R = 1000, cluster = \"firm\")\n\nOther:\n\nJupyter notebook support via output=\"jupyter\"\nBug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-24", + "href": "NEWS.html#section-24", + "title": "News", + "section": "", + "text": "modelsummary:\n\nnew arguments for modelsummary: group and group_map for grouped parameters (e.g., outcome levels in multinomial logit or components of gamlss model).\ndvnames() makes it easy to get dependent variable column titles (thanks to @NickCH-K)\noutput=\"modelsummary_list\" to save a lightweight list-based representation of the table which can be saved and fed to modelsummary once more to get a full table.\nvcov adds a row to note the type of standard errors.\nmodelsummary accepts a single model with multiple vcovs.\nget_gof forwards … to model_performance\ncoef_map accepts unnamed vectors for easy subsetting\nfixest::fixest_multi support\noptions(modelsummary_get) to set the order of extraction functions to use under the hood (broom vs. easystats vs. all)\nmetrics argument of performance::model_performance is available via modelsummary’s … ellipsis to limit the GOF statistics in Bayesian models.\nusers can omit the stars legend note by using glue strings: estimate=\"{estimate}{stars}\"\noutput=“html” can use gt by setting options(modelsummary_factory_html=\"gt\")\n\ndatasummary_correlation:\n\npasses ... forward\nnew function: datasummary_correlation_format\ndatasummary_correlation’s method argument accepts functions and “pearspear” (thanks to @joachim-gassen)\n\ndatasummary:\n\ndatasummary functions and rounding accept …, big.mark, etc.\n\ndatasummary_skim:\n\nnow works with haven_labeled numeric\nfaster tables with bayesian models.\n\nBug fixes and lints", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-25", + "href": "NEWS.html#section-25", + "title": "News", + "section": "", + "text": "new output format: latex_tabular\ntidy_custom allows partial term matches\nmodelsummary(coef_rename) accepts functions\nnew function coef_rename for use in modelsummary(coef_rename=coef_rename)\nmodelplot accepts add_rows to add reference categories\ninformative error message when estimate or statistic is not available\nbug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-26", + "href": "NEWS.html#section-26", + "title": "News", + "section": "", + "text": "statistic_override becomes vcov\nvcov accepts shortcuts: “robust”, “stata”, “HC0”, etc.\nvcov accepts formulas for clustered SEs: ~group\nmodelsummary_wide has a new “stacking” argument\nhtml horizontal rule to separate estimates form gof\ngof_map accepts list of lists. only needs 3 columns.\nsupport officedown Rmd\nestimate accepts a vector for per model estimates\noptions(modelsummary_default) can be markdown, html, latex\nbug: passing arguments through …\nbug: stars and rounding", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-27", + "href": "NEWS.html#section-27", + "title": "News", + "section": "", + "text": "glue format for estimate and statistic\neasystats support for model info extraction\ndeprecate statistic_vertical\ndeprecate extract_models. Use modelsummary(output=“dataframe”) instead.\nmodelplot pushes … through to modelsummary(output=“dataframe”)\ndatasummary_skim(type=“dataset”)\ngof_map omits by default\ndatasummary_balance uses row percentages\nstatistic_override does not require a list\nstatistic_override accepts a single model\nN function for well formatted N in datasummary\nBug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-28", + "href": "NEWS.html#section-28", + "title": "News", + "section": "", + "text": "new function: modelsummary_wide\ncoef_omit and gof_omit use grepl(perl=TRUE)\nfmt accepts integer, string or function and respects options(OutDec=“,”)\nalign argument for modelsummary\nalign is more liberal to accept dcolumn alignment\nglance_custom methods for lfe and fixest\nbug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-29", + "href": "NEWS.html#section-29", + "title": "News", + "section": "", + "text": "new argument: coef_rename\nnew function: datasummary_df\npreserve term order in modelsummary\nrefactor datasummary_balance\ndatasummary_skim uses svg histograms instead of unicode\nremoved 5 dependencies\npass … to kableExtra::kbl for more customization\ntest improvements\ninternal code style\nbug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-30", + "href": "NEWS.html#section-30", + "title": "News", + "section": "", + "text": "bug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-31", + "href": "NEWS.html#section-31", + "title": "News", + "section": "", + "text": "default HTML output factory is now kableExtra\ninteraction “:” gsubbed by “0d7”\ndependencies: removed 1 depends, 3 imports, and 3 suggests\nword_document knitr works out-of-the-box\nbug fixes", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-32", + "href": "NEWS.html#section-32", + "title": "News", + "section": "", + "text": "glance_custom.fixest ships with modelsummary", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-33", + "href": "NEWS.html#section-33", + "title": "News", + "section": "", + "text": "datasummary\ndatasummary_skim\ndatasummary_balance\ndatasummary_correlation\nmodelplot\nallow duplicate model names\nbug: can’t use coef_map with multiple statistics (thanks @sbw78)\nbug: wrong number of stars w/ statistic=‘p.value’ (thanks @torfason)\noutput=‘data.frame’. extract is no longer documented.", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-34", + "href": "NEWS.html#section-34", + "title": "News", + "section": "", + "text": "add_rows now accepts a data.frame with “position” and “section” columns\nadd_rows_location is deprecated\nbug in sanity_output prevented overwriting files", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-35", + "href": "NEWS.html#section-35", + "title": "News", + "section": "", + "text": "huxtable support\nflextable support\nestimate argument\nfixest tidiers\nwebsite and vignette improvements\ngof_map additions\nglance_custom\ntidy_custom", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-36", + "href": "NEWS.html#section-36", + "title": "News", + "section": "", + "text": "Out-of-the-box Rmarkdown compilation to HTML, PDF, RTF\nkableExtra output format for LaTeX and Markdown\nSupport for threeparttable, colors, and many other LaTeX options\nDeprecated arguments: filename, subtitle\nDeprecated functions: clean_latex, knit_latex\npkgdown website and doc improvements\nmitools tidiers\nNew tests", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-37", + "href": "NEWS.html#section-37", + "title": "News", + "section": "", + "text": "Convenience function to render markdown in row/column labels\nbug: breakage when all GOF were omitted\nClean up manual with @keywords internal\nbug: tidyr import", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-38", + "href": "NEWS.html#section-38", + "title": "News", + "section": "", + "text": "gt is now available on CRAN\nnew latex_env argument for knit_latex and clean_latex\nbug when all gof omitted\nbug in statistic_override with functions\nbug caused by upstream changes in tab_style\nbug caused by upstream changes in filename=‘rtf’\nAllow multiple rows of uncertainty estimates per coefficient\nPreserve add_rows order\nDisplay uncertainty estimates next to the coefficient with statistic_vertical = FALSE\nBetter clean_latex function\nCan display R2 and confidence intervals for mice-imputed lm-models\nInternal functions have @keywords internal to avoid inclusion in docs\nStatistic override accepts pre-formatted character vectors", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "NEWS.html#section-39", + "href": "NEWS.html#section-39", + "title": "News", + "section": "", + "text": "Initial release (gt still needs to be installed from github)", + "crumbs": [ + "Get started", + "News" + ] + }, + { + "objectID": "vignettes/modelsummary_extension.html", + "href": "vignettes/modelsummary_extension.html", + "title": "Extension and Customization", + "section": "", + "text": "library(modelsummary)\n\nUnsupported models: modelsummary_list\n\nThe simplest way to summarize an unsupported model is to create a modelsummary_list object. This approach is super flexible, but it requires manual intervention, and it can become tedious if you need to summarize many models. The next section shows how to add formal support for an unsupported model type.\nA modelsummary_list is a list with two element that conform to the broom package specification: tidy and glance. tidy is a data.frame with at least three columns: term, estimate, and std.error. glance is a data.frame with only a single row, and where each column will be displayed at the bottom of the table in the goodness-of-fit section. Finally, we wrap those two elements in a list and assign it a modelsummary_list class:\n\nti <- data.frame(\n term = c(\"coef1\", \"coef2\", \"coef3\"),\n estimate = 1:3,\n std.error = c(pi, exp(1), sqrt(2)))\n\ngl <- data.frame(\n stat1 = \"blah\",\n stat2 = \"blah blah\")\n\nmod <- list(\n tidy = ti,\n glance = gl)\nclass(mod) <- \"modelsummary_list\"\n\nmodelsummary(mod)\n\n \n\n \n \n\ntinytable_j3rpxlg4dt6svij5pz34\n\n\n \n\n \n (1)\n \n\n\ncoef1\n 1.000 \n \n\n \n (3.142) \n \n\ncoef2\n 2.000 \n \n\n \n (2.718) \n \n\ncoef3\n 3.000 \n \n\n \n (1.414) \n \n\nstat1\n blah \n \n\nstat2\n blah blah\n \n\n\n\n\n \n\n\nUnsupported models: glance and tidy\n\nmodelsummary relies on two functions from the broom package to extract model information: tidy and glance. If broom doesn’t support the type of model you are trying to summarize, modelsummary won’t support it out of the box. Thankfully, it is extremely easy to add support for most models using custom methods.\nFor example, models produced by the MCMCglmm package are not currently supported by broom. To add support, you simply need to create a tidy and a glance method:\n# load packages and data\nlibrary(modelsummary)\nlibrary(MCMCglmm)\ndata(PlodiaPO)\n\n# add custom functions to extract estimates (tidy) and goodness-of-fit (glance) information\ntidy.MCMCglmm <- function(x, ...) {\n s <- summary(x, ...)\n ret <- data.frame(\n term = row.names(s$solutions),\n estimate = s$solutions[, 1],\n conf.low = s$solutions[, 2],\n conf.high = s$solutions[, 3])\n ret\n}\n\nglance.MCMCglmm <- function(x, ...) {\n ret <- data.frame(\n dic = x$DIC,\n n = nrow(x$X))\n ret\n}\n\n# estimate a simple model\nmodel <- MCMCglmm(PO ~ 1 + plate, random = ~ FSfamily, data = PlodiaPO, verbose=FALSE, pr=TRUE)\n\n# summarize the model\nmodelsummary(model, statistic = 'conf.int')\nThree important things to note.\nFirst, the methods are named tidy.MCMCglmm and glance.MCMCglmm because the model object I am trying to summarize is of class MCMCglmm. You can find the class of a model by running: class(model).\nSecond, both of the methods include the ellipsis ... argument.\nThird, in the example above we used the statistic = 'conf.int' argument. This is because the tidy method produces conf.low and conf.high columns. In most cases, users will define std.error column in their custom tidy methods, so the statistic argument will need to be adjusted.\nIf you create new tidy and glance methods, please consider contributing them to broom so that the rest of the community can benefit from your work: https://github.com/tidymodels/broom\nModifying information: tidy_custom and glance_custom\n\nUsers may want to include more information than is made available by the default extractor function. For example, models produced by the MASS::polr do not produce p values by default, which means that we cannot use the stars=TRUE argument in modelsummary. However, it is possible to extract this information by using the lmtest::coeftest function. To include such custom information, we will define new glance_custom and tidy_custom methods.\nWe begin by estimating a model with the MASS::polr:\n\nlibrary(MASS)\n\nmod_ordinal <- polr(as.ordered(gear) ~ mpg + drat, data = mtcars)\n\nget_estimates(mod_ordinal)\n\n term estimate std.error conf.level conf.low conf.high statistic df.error p.value component s.value group\n1 3|4 13.962948761 4.04107300 0.95 5.6851860 22.2407116 3.45525774 28 0.0017706303 alpha 9.1 \n2 4|5 16.898937342 4.39497069 0.95 7.8962480 25.9016267 3.84506258 28 0.0006356348 alpha 10.6 \n3 mpg -0.008646682 0.09034201 0.95 -0.1916706 0.1708667 -0.09571053 28 0.9244322098 beta 0.1 \n4 drat 3.949431923 1.30665144 0.95 1.6191505 6.8457246 3.02255965 28 0.0053120619 beta 7.6 \n\n\nThe get_estimates function shows that our default extractor does not produce a p.value column. As a result, setting stars=TRUE in modelsummary will produce an error.\nWe know that the MASS::polr produces an object of class polr:\n\nclass(mod_ordinal)\n\n[1] \"polr\"\n\n\nTo extract more (custom) information from a model of this class, we thus define a method called tidy_custom.polr which returns a data.frame with two columns: term and p.value:\n\ntidy_custom.polr <- function(x, ...) {\n s <- lmtest::coeftest(x)\n out <- data.frame(\n term = row.names(s),\n p.value = s[, \"Pr(>|t|)\"])\n out\n}\n\nWhen this method is defined, modelsummary can automatically extract p values from all models of this class, and will now work properly with stars=TRUE:\n\nmodelsummary(mod_ordinal, stars = TRUE)\n\n \n\n \n \n\ntinytable_nkgbay6upgof104ksq19\n\n\n \n\n \n (1)\n \n+ p \n\n\n3|4 \n 13.963** \n \n\n \n (4.041) \n \n\n4|5 \n 16.899***\n \n\n \n (4.395) \n \n\nmpg \n -0.009 \n \n\n \n (0.090) \n \n\ndrat \n 3.949** \n \n\n \n (1.307) \n \n\nNum.Obs.\n 32 \n \n\nAIC \n 51.1 \n \n\nBIC \n 57.0 \n \n\nRMSE \n 3.44 \n \n\n\n\n\n \n\n\nNew information: tidy_custom and glance_custom\n\nSometimes users will want to include information that is not supplied by those functions. A pretty easy way to include extra information is to define new glance_custom and tidy_custom methods. To illustrate, we estimate two linear regression models using the lm function:\n\nlibrary(modelsummary)\n\nmod <- list()\nmod[[1]] <- lm(hp ~ mpg + drat, mtcars)\nmod[[2]] <- lm(wt ~ mpg + drat + am, mtcars)\n\nIn R, the lm function produces models of class “lm”:\n\nclass(mod[[1]])\n\n[1] \"lm\"\n\n\nLet’s say you would like to print the dependent variable for each model of this particular class. All you need to do is define a new method called glance_custom.lm. This method should return a data.frame (or tibble) with 1 row, and 1 column per piece of information you want to display. For example:\n\nglance_custom.lm <- function(x, ...) {\n dv <- as.character(formula(x)[2])\n out <- data.frame(\"DV\" = dv)\n return(out)\n}\n\nNow, let’s customize the body of the table. The vcov argument already allows users to customize uncertainty estimates. But imagine you want to override the coefficient estimates of your “lm” models. Easy! All you need to do is define a tidy_custom.lm method which returns a data.frame (or tibble) with one column called “term” and one column called “estimate”.\nHere, we’ll substitute estimates by an up/down-pointing triangles which represents their signs:\n\ntidy_custom.lm <- function(x, ...) {\n s <- summary(x)$coefficients\n out <- data.frame(\n term = row.names(s),\n estimate = ifelse(s[,1] > 0, '▲', '▼'))\n return(out)\n}\n\nAfter you define the glance_custom and tidy_custom methods, modelsummary will automatically display your customized model information:\n\nmodelsummary(mod)\n\n \n\n \n \n\ntinytable_9fk3qlzheod0kheqfysh\n\n\n \n\n \n (1)\n (2)\n \n\n\n(Intercept)\n ▲ \n ▲ \n \n\n \n (55.415)\n (0.728)\n \n\nmpg \n ▼ \n ▼ \n \n\n \n (1.792) \n (0.019)\n \n\ndrat \n ▲ \n ▼ \n \n\n \n (20.198)\n (0.245)\n \n\nam \n \n ▼ \n \n\n \n \n (0.240)\n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 \n 0.614 \n 0.803 \n \n\nR2 Adj. \n 0.588 \n 0.782 \n \n\nAIC \n 337.9 \n 46.4 \n \n\nBIC \n 343.7 \n 53.7 \n \n\nLog.Lik. \n -164.940\n -18.201\n \n\nF \n 23.100 \n 38.066 \n \n\nRMSE \n 41.91 \n 0.43 \n \n\nDV \n hp \n wt \n \n\n\n\n\n \n\n\nNote that you can define a std.error column in tidy_custom.lm to replace the uncertainty estimates instead of the coefficients.\nCustomization: New model class\nAn even more fundamental way to customize the output would be to completely bypass modelsummary’s extractor functions by assigning a new class name to your model. For example,\n\n# estimate a linear model\nmod_custom <- lm(hp ~ mpg + drat, mtcars)\n\n# assign it a new class\nclass(mod_custom) <- \"custom\"\n\n# define tidy and glance methods\ntidy.custom <- function(x, ...) {\n data.frame(\n term = names(coef(x)),\n estimate = letters[1:length(coef(x))],\n std.error = seq_along(coef(x))\n )\n}\n\nglance.custom <- function(x, ...) {\n data.frame(\n \"Model\" = \"Custom\",\n \"nobs\" = stats:::nobs.lm(x)\n )\n}\n\n# summarize\nmodelsummary(mod_custom)\n\n \n\n \n \n\ntinytable_zcojavccn7wsaent64n4\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n a \n \n\n \n (1.000)\n \n\nmpg \n b \n \n\n \n (2.000)\n \n\ndrat \n c \n \n\n \n (3.000)\n \n\nNum.Obs. \n 32 \n \n\nModel \n Custom \n \n\n\n\n\n \n\n\nWarning: When defining new tidy and glance methods, it is important to include an ellipsis argument (...).\nNote that in the glance.custom() method, we called stats:::nobs.lm() instead of the default stats::nobs() method, because the latter know does not know where to dispatch models of our new “custom” class. Being more explicit solves the problem.\nAn alternative would be to set a new class that inherits from the previous one, and to use a global option to set broom as the default extractor function (otherwise modelsummary will use its standard lm extractors by inheritance):\n\noptions(modelsummary_get = \"broom\")\nclass(mod_custom) <- c(\"custom\", \"lm\")\n\nCustomization: modelsummary_list\n\nAnother flexible way to customize model output is to use output = \"modelsummary_list\". With this output option, modelsummary() returns a list with two elements: tidy contains parameter estimates, standard errors, etc., and glance contains model statistics such as the AIC. For example,\n\nmod <- lm(hp ~ mpg + drat, mtcars)\nmod_list <- modelsummary(mod, output = \"modelsummary_list\")\nmod_list$tidy\n\n term estimate std.error statistic df.error p.value s.value group conf.low conf.high\n1 (Intercept) 278.515455 55.414866 5.0260061 29 2.359726e-05 15.4 NA NA\n2 mpg -9.985499 1.791837 -5.5727709 29 5.172030e-06 17.6 NA NA\n3 drat 19.125752 20.197756 0.9469246 29 3.515013e-01 1.5 NA NA\n\nmod_list$glance\n\n aic bic r.squared adj.r.squared rmse nobs F logLik\n1 337.8809 343.7438 0.6143611 0.5877653 41.90687 32 23.09994 -164.9404\n\n\nBoth tidy and glance can now be customized, and the updated model can be passed back to modelsummary using modelsummary(mod_list). All information that is displayed in the table is contained in mod_list, so this pattern allows for very flexible adjustments of output tables.\nA useful example for this pattern concerns mixed models using lme4. Assume we want to compare the effect of using different degrees-of-freedom adjustments on the significance of the coefficients. The models have identical parameter estimates, standard errors, and model fit statistics - we only want to change the p-values. We use the parameters package to compute the adjusted p-values.\n\nlibrary(\"lme4\")\nmod <- lmer(mpg ~ drat + (1 | am), data = mtcars)\nmod_list <- modelsummary(mod, output = \"modelsummary_list\", effects = \"fixed\")\n# create a copy, where we'll change the p-values\nmod_list_kenward <- as.list(mod_list)\nmod_list_kenward$tidy$p.value <- parameters::p_value_kenward(mod)$p\n\nmodelsummary(list(\"Wald\" = mod_list, \"Kenward\" = mod_list_kenward), \n statistic = \"{std.error} ({p.value}) {stars}\")\n\n \n\n \n \n\ntinytable_o3yljn4kcrac80bwor9a\n\n\n \n\n \n Wald\n Kenward\n \n\n\n(Intercept)\n -5.159 \n -5.159 \n \n\n \n 6.409 (0.428) \n 6.409 (0.680) \n \n\ndrat \n 7.045 \n 7.045 \n \n\n \n 1.736 (\n \n1.736 (0.086) +\n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 Marg. \n 0.402 \n 0.402 \n \n\nR2 Cond. \n 0.440 \n 0.440 \n \n\nAIC \n 188.7 \n 188.7 \n \n\nBIC \n 194.6 \n 194.6 \n \n\nICC \n 0.1 \n 0.1 \n \n\nRMSE \n 4.28 \n 4.28", + "crumbs": [ + "Get started", + "Extension and Customization" + ] + }, + { + "objectID": "vignettes/datasummary.html", + "href": "vignettes/datasummary.html", + "title": "Data Summaries", + "section": "", + "text": "datasummary is a function from the modelsummary package. It allows us to create data summaries, frequency tables, crosstabs, correlation tables, balance tables (aka “Table 1”), and more. It has many benefits:\nThis tutorial will show how to draw tables like these (and more!):\ndatasummary is built around the fantastic tables package for R. It is a thin “wrapper” which adds convenience functions and arguments; a user-interface consistent with modelsummary; cleaner html output; and the ability to export tables to more formats, including gt tables, flextable objects, and Microsoft Word documents.\ndatasummary is a general-purpose table-making tool. It allows us to build (nearly) any summary table we want by using simple 2-sided formulae. For example, in the expression x + y ~ mean + sd, the left-hand side of the formula identifies the variables or statistics to display as rows, and the right-hand side defines the columns. Below, we will see how variables and statistics can be “nested” with the * operator to produce tables like the ones above.\nIn addition to datasummary, the modelsummary package includes a “family” of companion functions named datasummary_*. These functions facilitate the production of standard, commonly used tables. This family currently includes:\nIn the next three sections, we illustrate how to use datasummary_balance, datasummary_correlation, datasummary_skim, and datasummary_crosstab. Then, we dive into datasummary itself to highlight its ease and flexibility.", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#custom-summary-functions", + "href": "vignettes/datasummary.html#custom-summary-functions", + "title": "Data Summaries", + "section": "Custom summary functions", + "text": "Custom summary functions\nThe Mean function is a shortcut supplied by modelsummary, and it is equivalent to mean(x,na.rm=TRUE). Since the flipper_length_mm variable includes missing observation, using the mean formula (with default na.rm=FALSE) would produce a missing/empty cell:\n\ndatasummary(flipper_length_mm ~ mean,\n data = penguins)\n\n \n\n \n \n\ntinytable_gmkbnknsg9dbs7d4wso2\n\n\n \n\n \n mean\n \n\nflipper_length_mm\n \n \n\n\n\n \n\n\nmodelsummary supplies these functions: Mean, SD, Min, Max, Median, P0, P25, P50, P75, P100, Histogram, and a few more (see the package documentation).\nUsers are also free to create and use their own custom summaries. Any R function which takes a vector and produces a single value is acceptable. For example, the Range functions return a numerical value, and the MinMax returns a string:\n\nRange <- function(x) max(x, na.rm = TRUE) - min(x, na.rm = TRUE)\n\ndatasummary(flipper_length_mm ~ Range,\n data = penguins)\n\n \n\n \n \n\ntinytable_j1e99w0p98bh76b91fco\n\n\n \n\n \n Range\n \n\nflipper_length_mm\n 59.00\n \n\n\n\n \n\nMinMax <- function(x) paste0('[', min(x, na.rm = TRUE), ', ', max(x, na.rm = TRUE), ']')\n\ndatasummary(flipper_length_mm ~ MinMax,\n data = penguins)\n\n \n\n \n \n\ntinytable_m6msntnnf9fp8e82tas5\n\n\n \n\n \n MinMax\n \n\nflipper_length_mm\n [172, 231]", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#concatenating-with", + "href": "vignettes/datasummary.html#concatenating-with", + "title": "Data Summaries", + "section": "Concatenating with +\n", + "text": "Concatenating with +\n\nTo include more rows and columns, we use the + sign:\n\ndatasummary(flipper_length_mm + body_mass_g ~ Mean + SD,\n data = penguins)\n\n \n\n \n \n\ntinytable_jz9odiw0rb1tprw7356f\n\n\n \n\n \n Mean\n SD\n \n\n\nflipper_length_mm\n 200.92 \n 14.06 \n \n\nbody_mass_g \n 4201.75\n 801.95\n \n\n\n\n\n \n\n\nSometimes, it can be cumbersome to list all variables separated by + signs. The All() function is a useful shortcut:\n\ndatasummary(All(penguins) ~ Mean + SD,\n data = penguins)\n\n \n\n \n \n\ntinytable_fpe8szyir8ebc9hoqajp\n\n\n \n\n \n Mean\n SD\n \n\n\nrownames \n 172.50 \n 99.45 \n \n\nbill_length_mm \n 43.92 \n 5.46 \n \n\nbill_depth_mm \n 17.15 \n 1.97 \n \n\nflipper_length_mm\n 200.92 \n 14.06 \n \n\nbody_mass_g \n 4201.75\n 801.95\n \n\nyear \n 2008.03\n 0.82 \n \n\n\n\n\n \n\n\nBy default, All selects all numeric variables. This behavior can be changed by modifying the function’s arguments. See ?All for details.", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#nesting-with", + "href": "vignettes/datasummary.html#nesting-with", + "title": "Data Summaries", + "section": "Nesting with *\n", + "text": "Nesting with *\n\ndatasummary can nest variables and statistics inside categorical variables using the * symbol. When applying the the * operator to factor, character, or logical variables, columns or rows will automatically be nested. For instance, if we want to display separate means for each value of the variable sex, we use mean * sex:\n\ndatasummary(flipper_length_mm + body_mass_g ~ mean * sex,\n data = penguins)\n\n \n\n \n \n\ntinytable_5hc3q270kk17d3xu3iq8\n\n\n \n\n \n female\n male\n \n\n\nflipper_length_mm\n 197.36 \n 204.51 \n \n\nbody_mass_g \n 3862.27\n 4545.68\n \n\n\n\n\n \n\n\nWe can use parentheses to nest several terms inside one another, using a call of this form: x * (y + z). Here is an example with nested columns:\n\ndatasummary(body_mass_g ~ sex * (mean + sd),\n data = penguins)\n\n \n\n \n \n\ntinytable_cilcylzojaj6eqe8vwnn\n\n\n \n\n\n \nfemale\nmale\n\n\n \n mean\n sd\n mean\n sd\n \n\n\nbody_mass_g\n 3862.27\n 666.17\n 4545.68\n 787.63\n \n\n\n\n \n\n\nHere is an example with nested rows:\n\ndatasummary(sex * (body_mass_g + flipper_length_mm) ~ mean + sd,\n data = penguins)\n\n \n\n \n \n\ntinytable_w27wjhsaw7brd2zo6xv3\n\n\n \n\nsex\n \n mean\n sd\n \n\n\nfemale\n body_mass_g \n 3862.27\n 666.17\n \n\n \n flipper_length_mm\n 197.36 \n 12.50 \n \n\nmale \n body_mass_g \n 4545.68\n 787.63\n \n\n \n flipper_length_mm\n 204.51 \n 14.55 \n \n\n\n\n\n \n\n\nThe order in which terms enter the formula determines the order in which labels are displayed. For example, this shows island above sex:\n\ndatasummary(flipper_length_mm + body_mass_g ~ mean * island * sex,\n data = penguins)\n\n \n\n \n \n\ntinytable_0z11rz6aqhv67q2ggqx9\n\n\n \n\n\n \nBiscoe\nDream\nTorgersen\n\n\n \n female\n male\n female\n male\n female\n male\n \n\n\n\nflipper_length_mm\n 205.69 \n 213.29 \n 190.02 \n 196.31 \n 188.29 \n 194.91 \n \n\nbody_mass_g \n 4319.38\n 5104.52\n 3446.31\n 3987.10\n 3395.83\n 4034.78\n \n\n\n\n\n \n\n\nThis shows sex above island values:\n\ndatasummary(flipper_length_mm + body_mass_g ~ mean * sex * island,\n data = penguins)\n\n \n\n \n \n\ntinytable_a9g5byj5w3m2p0phaqp5\n\n\n \n\n\n \nfemale\nmale\n\n\n \n Biscoe\n Dream\n Torgersen\n Biscoe\n Dream\n Torgersen\n \n\n\n\nflipper_length_mm\n 205.69 \n 190.02 \n 188.29 \n 213.29 \n 196.31 \n 194.91 \n \n\nbody_mass_g \n 4319.38\n 3446.31\n 3395.83\n 5104.52\n 3987.10\n 4034.78\n \n\n\n\n\n \n\n\nBy default, datasummary omits column headers with a single value/label across all columns, except for the header that sits just above the data. If the header we want to see is not displayed, we may want to reorder the terms of the formula. To show all headers, set sparse_header=FALSE:\n\ndatasummary(flipper_length_mm + body_mass_g ~ mean * sex * island,\n data = penguins,\n sparse_header = FALSE)\n\n \n\n \n \n\ntinytable_o3ai0bv4e07vt7pt6iez\n\n\n \n\n\n \nfemale\nmale\n\n\n \n Biscoe\n Dream\n Torgersen\n Biscoe\n Dream\n Torgersen\n \n\n\n\nflipper_length_mm\n 205.69 \n 190.02 \n 188.29 \n 213.29 \n 196.31 \n 194.91 \n \n\nbody_mass_g \n 4319.38\n 3446.31\n 3395.83\n 5104.52\n 3987.10\n 4034.78\n \n\n\n\n\n \n\n\nWhen using sparse_header=FALSE, it is often useful to insert Heading() * in the table formula, in order to rename or omit some of the labels manually. Type ?tables::Heading for details and examples.", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#renaming-with", + "href": "vignettes/datasummary.html#renaming-with", + "title": "Data Summaries", + "section": "Renaming with =\n", + "text": "Renaming with =\n\nPersonally, I prefer to rename variables and values before drawing my tables, using backticks when variable names include whitespace. For example,\n\ntmp <- penguins %>%\n select(`Flipper length (mm)` = flipper_length_mm,\n `Body mass (g)` = body_mass_g)\n\ndatasummary(`Flipper length (mm)` + `Body mass (g)` ~ Mean + SD,\n data = tmp)\n\n \n\n \n \n\ntinytable_l1df4fw6ykbqlfthy5uq\n\n\n \n\n \n Mean\n SD\n \n\n\nFlipper length (mm)\n 200.92 \n 14.06 \n \n\nBody mass (g) \n 4201.75\n 801.95\n \n\n\n\n\n \n\n\nHowever, thanks to the tables package, datasummary offers two additional mechanisms to rename. First, we can wrap a term in parentheses and use the equal = sign: (NewName=OldName):\n\ndatasummary((`Flipper length (mm)` = flipper_length_mm) + (`Body mass (g)` = body_mass_g) ~\n island * ((Avg. = Mean) + (Std.Dev. = SD)),\n data = penguins)\n\n \n\n \n \n\ntinytable_q562iihrzrltd3omj3wu\n\n\n \n\n\n \nBiscoe\nDream\nTorgersen\n\n\n \n Avg.\n Std.Dev.\n Avg.\n Std.Dev.\n Avg.\n Std.Dev.\n \n\n\n\nFlipper length (mm)\n 209.71 \n 14.14 \n 193.07 \n 7.51 \n 191.20 \n 6.23 \n \n\nBody mass (g) \n 4716.02\n 782.86\n 3712.90\n 416.64\n 3706.37\n 445.11\n \n\n\n\n\n \n\n\nSecond, we can use the Heading() function:\n\ndatasummary(Heading(\"Flipper length (mm)\") * flipper_length_mm + Heading(\"Body mass (g)\") * body_mass_g ~ island * (Mean + SD),\n data = penguins)\n\n \n\n \n \n\ntinytable_42kmj5amrwnqfri6id0g\n\n\n \n\n\n \nBiscoe\nDream\nTorgersen\n\n\n \n Mean\n SD\n Mean\n SD\n Mean\n SD\n \n\n\n\nFlipper length (mm)\n 209.71 \n 14.14 \n 193.07 \n 7.51 \n 191.20 \n 6.23 \n \n\nBody mass (g) \n 4716.02\n 782.86\n 3712.90\n 416.64\n 3706.37\n 445.11\n \n\n\n\n\n \n\n\nThe Heading function also has a nearData argument which can be useful in cases where some rows are nested but others are not. Compare the last row of these two tables:\n\ndatasummary(sex * (flipper_length_mm + bill_length_mm) + Heading(\"Body mass (g)\") * body_mass_g ~ Mean + SD,\n data = penguins)\n\n \n\n \n \n\ntinytable_z0m6uhwkdk24qaiawiuf\n\n\n \n\nsex\n \n Mean\n SD\n \n\n\nfemale\n flipper_length_mm\n 197.36 \n 12.50 \n \n\n \n bill_length_mm \n 42.10 \n 4.90 \n \n\nmale \n flipper_length_mm\n 204.51 \n 14.55 \n \n\n \n bill_length_mm \n 45.85 \n 5.37 \n \n\n \n Body mass (g) \n 4201.75\n 801.95\n \n\n\n\n\n \n\ndatasummary(sex * (flipper_length_mm + bill_length_mm) + Heading(\"Body mass (g)\", nearData=FALSE) * body_mass_g ~ Mean + SD,\n data = penguins)\n\n \n\n \n \n\ntinytable_q1qh5myyxgetbfabh6jb\n\n\n \n\nsex\n \n Mean\n SD\n \n\n\nfemale \n flipper_length_mm\n 197.36 \n 12.50 \n \n\n \n bill_length_mm \n 42.10 \n 4.90 \n \n\nmale \n flipper_length_mm\n 204.51 \n 14.55 \n \n\n \n bill_length_mm \n 45.85 \n 5.37 \n \n\nBody mass (g)\n \n 4201.75\n 801.95", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#counts-and-percentages", + "href": "vignettes/datasummary.html#counts-and-percentages", + "title": "Data Summaries", + "section": "Counts and Percentages", + "text": "Counts and Percentages\nThe tables package allows datasummary to use neat tricks to produce frequency tables:\n\nAdd a N to the right-hand side of the equation.\nAdd Percent() to the right-hand side to calculate the percentage of observations in each cell.\nAdd 1 to the left-hand side to include a row with the total number of observations:\n\n\ndatasummary(species * sex + 1 ~ N + Percent(),\n data = penguins)\n\n \n\n \n \n\ntinytable_4oiqdzsiqr8226nhkgc4\n\n\n \n\nspecies\n sex\n N\n Percent\n \n\n\nAdelie \n female\n 73 \n 21.22 \n \n\n \n male \n 73 \n 21.22 \n \n\nChinstrap\n female\n 34 \n 9.88 \n \n\n \n male \n 34 \n 9.88 \n \n\nGentoo \n female\n 58 \n 16.86 \n \n\n \n male \n 61 \n 17.73 \n \n\n \n All \n 344\n 100.00\n \n\n\n\n\n \n\n\nNote that the Percent() function accepts a denom argument to determine if percentages should be calculated row or column-wise, or if they should take into account all cells.", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#weighted-percentages", + "href": "vignettes/datasummary.html#weighted-percentages", + "title": "Data Summaries", + "section": "Weighted percentages", + "text": "Weighted percentages\nThe Percent() pseudo-function also accepts a fn argument, which must be a function which accepts two vectors: x is the values in the current cell, and y is all the values in the whole dataset. The default fn is:\n\ndatasummary(species * sex + 1 ~ N + Percent(fn = function(x, y) 100 * length(x) / length(y)),\n data = penguins)\n\n \n\n \n \n\ntinytable_jsa0bvkvf60q065zqe8n\n\n\n \n\nspecies\n sex\n N\n Percent\n \n\n\nAdelie \n female\n 73 \n 21.22 \n \n\n \n male \n 73 \n 21.22 \n \n\nChinstrap\n female\n 34 \n 9.88 \n \n\n \n male \n 34 \n 9.88 \n \n\nGentoo \n female\n 58 \n 16.86 \n \n\n \n male \n 61 \n 17.73 \n \n\n \n All \n 344\n 100.00\n \n\n\n\n\n \n\n\nThe code above takes the number of elements in the cell length(x) and divides it by the number of total elements length(y).\nNow, let’s say we want to display percentages weighted by one of the variables of the dataset. This can often be useful with survey weights, for example. Here, we use an arbitrary column of weights called flipper_length_mm:\n\nwtpct <- function(x, y) sum(x, na.rm = TRUE) / sum(y, na.rm = TRUE) * 100\ndatasummary(species * sex + 1 ~ N + flipper_length_mm * Percent(fn = wtpct),\n data = penguins)\n\n \n\n \n \n\ntinytable_ubh94hnbw1kbbhs1z17n\n\n\n \n\nspecies\n sex\n N\n Percent\n \n\n\nAdelie \n female\n 73 \n 19.95 \n \n\n \n male \n 73 \n 20.44 \n \n\nChinstrap\n female\n 34 \n 9.49 \n \n\n \n male \n 34 \n 9.89 \n \n\nGentoo \n female\n 58 \n 17.95 \n \n\n \n male \n 61 \n 19.67 \n \n\n \n All \n 344\n 100.00\n \n\n\n\n\n \n\n\nIn each cell we now have the sum of weights in that cell, divided by the total sum of weights in the column.", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#custom-percentages", + "href": "vignettes/datasummary.html#custom-percentages", + "title": "Data Summaries", + "section": "Custom percentages", + "text": "Custom percentages\nHere is another simple illustration of Percent function mechanism in action, where we combine counts and percentages in a simple nice label:\n\ndat <- mtcars\ndat$cyl <- as.factor(dat$cyl)\n\nfn <- function(x, y) {\n out <- sprintf(\n \"%s (%.1f%%)\",\n length(x),\n length(x) / length(y) * 100)\n}\ndatasummary(\n cyl ~ Percent(fn = fn),\n data = dat)\n\n \n\n \n \n\ntinytable_ne5jddm7lnfjb8raeoh6\n\n\n \n\ncyl\n Percent\n \n\n\n4\n 11 (34.4%)\n \n\n6\n 7 (21.9%) \n \n\n8\n 14 (43.8%)", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#factor", + "href": "vignettes/datasummary.html#factor", + "title": "Data Summaries", + "section": "Factor", + "text": "Factor\nThe * nesting operator that we used above works automatically for factor, character, and logical variables. Sometimes, it is convenient to use it with other types of variables, such as binary numeric variables. In that case, we can wrap the variable name inside a call to Factor(). This allows us to treat a variable as factor, without having to modify it in the original data. For example, in the mtcars data, there is a binary numeric variable call am. We nest statistics within categories of am by typing:\n\ndatasummary(mpg + hp ~ Factor(am) * (mean + sd),\n data = mtcars)\n\n \n\n \n \n\ntinytable_5l3c7wwc9ffk7su8j1zl\n\n\n \n\n\n \n0\n1\n\n\n \n mean\n sd\n mean\n sd\n \n\n\n\nmpg\n 17.15 \n 3.83 \n 24.39 \n 6.17 \n \n\nhp \n 160.26\n 53.91\n 126.85\n 84.06", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#arguments-na.rmtrue", + "href": "vignettes/datasummary.html#arguments-na.rmtrue", + "title": "Data Summaries", + "section": "\nArguments: na.rm=TRUE\n", + "text": "Arguments: na.rm=TRUE\n\nWe can pass any argument to the summary function by including a call to Arguments(). For instance, there are missing values in the flipper_length_mm variable of the penguins dataset. Therefore, the standard mean function will produce no result, because its default argument is na.rm=FALSE. We can change that by calling:\n\ndatasummary(flipper_length_mm ~ mean + mean*Arguments(na.rm=TRUE),\n data = penguins)\n\n \n\n \n \n\ntinytable_1pr57ay39ftz1ti891i7\n\n\n \n\n \n mean\n mean \n \n\nflipper_length_mm\n \n 200.92\n \n\n\n\n \n\n\nNotice that there is an empty cell (NA) under the normal mean function, but that the mean call with Arguments(na.rm=TRUE) produced a numeric result.\nWe can pass the same arguments to multiple functions using the parentheses:\n\ndatasummary(flipper_length_mm ~ (mean + sd) * Arguments(na.rm=TRUE),\n data = penguins)\n\n \n\n \n \n\ntinytable_5gl55tjokliekijsa0fp\n\n\n \n\n \n mean\n sd\n \n\nflipper_length_mm\n 200.92\n 14.06\n \n\n\n\n \n\n\nNote that the shortcut functions that modelsummary supplies use na.rm=TRUE by default, so we can use them directly without arguments, even when there are missing values:\n\ndatasummary(flipper_length_mm ~ Mean + Var + P75 + Range,\n data = penguins)\n\n \n\n \n \n\ntinytable_2crh9dfo2okr42i4yx76\n\n\n \n\n \n Mean\n Var\n P75\n Range\n \n\nflipper_length_mm\n 200.92\n 197.73\n 213.00\n 59.00", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#arguments-weighted-mean", + "href": "vignettes/datasummary.html#arguments-weighted-mean", + "title": "Data Summaries", + "section": "\nArguments: Weighted Mean", + "text": "Arguments: Weighted Mean\nYou can use the Arguments mechanism to do various things, such as calculating weighted means:\n\nnewdata <- data.frame(\n x = rnorm(20),\n w = rnorm(20),\n y = rnorm(20))\n\ndatasummary(x + y ~ weighted.mean * Arguments(w = w),\n data = newdata)\n\n \n\n \n \n\ntinytable_5qr7gp07pfpwbhdeivhx\n\n\n \n\n \n weighted.mean\n \n\n\nx\n 0.43 \n \n\ny\n -5.49\n \n\n\n\n\n \n\n\nWhich produces the same results as:\n\nweighted.mean(newdata$x, newdata$w)\n\n[1] 0.4323834\n\nweighted.mean(newdata$y, newdata$w)\n\n[1] -5.486109\n\n\nBut different results from:\n\nmean(newdata$x)\n\n[1] -0.03057975\n\nmean(newdata$y)\n\n[1] -0.06711904", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#logical-subsets", + "href": "vignettes/datasummary.html#logical-subsets", + "title": "Data Summaries", + "section": "Logical subsets", + "text": "Logical subsets\nCool stuff is possible with logical subsets:\n\ndatasummary((bill_length_mm > 44.5) + (bill_length_mm <= 44.5) ~ Mean * flipper_length_mm,\n data = penguins)\n\n \n\n \n \n\ntinytable_yci9nl094rd54beco9lu\n\n\n \n\n\n \n \n\n\nbill_length_mm > 44.5 \n 209.68\n \n\nbill_length_mm \n \n192.45\n \n\n\n\n\n \n\n\nSee the tables package documentation for more details and examples.", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#missing-values", + "href": "vignettes/datasummary.html#missing-values", + "title": "Data Summaries", + "section": "Missing values", + "text": "Missing values\nAt least 3 distinct issues can arise related to missing values.\nFunctions and na.rm\n\nAn empty cell can appear in the table when a statistical function returns NA instead of a numeric value. In those cases, you should:\n\nMake sure that your statistical function (e.g., mean or sd) uses na.rm=TRUE by default\nUse the Arguments strategy to set na.rm=TRUE (see the Arguments section of this vignette).\nUse a convenience function supplied by modelsummary, where na.rm is TRUE by default: Mean, SD, P25, etc.\nEmpty crosstab cells\nAn empty cell can appear in the table when a crosstab is deeply nested, and there are no observations for a given combination of covariates. In those cases, you can use the * DropEmpty pseudo-function. See the “Empty cells” section of this vignette for examples.\n\ndatasummary(island * species * body_mass_g ~ sex * (Mean + SD),\n data = penguins)\n\n \n\n \n \n\ntinytable_1f24cy9rgp2sbabygmu7\n\n\n \n\n\n \n \n \nfemale\nmale\n\n\nisland\n species\n \n Mean\n SD\n Mean\n SD\n \n\n\n\nBiscoe \n Adelie \n body_mass_g\n 3369.32\n 343.47\n 4050.00\n 355.57\n \n\n \n Chinstrap\n body_mass_g\n \n \n \n \n \n\n \n Gentoo \n body_mass_g\n 4679.74\n 281.58\n 5484.84\n 313.16\n \n\nDream \n Adelie \n body_mass_g\n 3344.44\n 212.06\n 4045.54\n 330.55\n \n\n \n Chinstrap\n body_mass_g\n 3527.21\n 285.33\n 3938.97\n 362.14\n \n\n \n Gentoo \n body_mass_g\n \n \n \n \n \n\nTorgersen\n Adelie \n body_mass_g\n 3395.83\n 259.14\n 4034.78\n 372.47\n \n\n \n Chinstrap\n body_mass_g\n \n \n \n \n \n\n \n Gentoo \n body_mass_g\n \n \n \n \n \n\n\n\n\n \n\ndatasummary(island * species * body_mass_g ~ sex * (Mean + SD) * DropEmpty(),\n data = penguins)\n\n \n\n \n \n\ntinytable_pszc9mhzt5mv9toh1jfg\n\n\n \n\n\n \n \n \nfemale\nmale\n\n\nisland\n species\n \n Mean\n SD\n Mean\n SD\n \n\n\n\nBiscoe \n Adelie \n body_mass_g\n 3369.32\n 343.47\n 4050.00\n 355.57\n \n\n \n Gentoo \n body_mass_g\n 4679.74\n 281.58\n 5484.84\n 313.16\n \n\nDream \n Adelie \n body_mass_g\n 3344.44\n 212.06\n 4045.54\n 330.55\n \n\n \n Chinstrap\n body_mass_g\n 3527.21\n 285.33\n 3938.97\n 362.14\n \n\nTorgersen\n Adelie \n body_mass_g\n 3395.83\n 259.14\n 4034.78\n 372.47\n \n\n\n\n\n \n\n\nPercent()\nBy default, the Percent() function computes the share of each category with respect to the whole data, including missing observations, but we can work around this with some trickery:jig\n\ndat <- data.frame(z = c(0,0,1,0,NA,0,1))\n\nprop.table(table(dat$z))\n\n\n 0 1 \n0.6666667 0.3333333 \n\ndatasummary(Factor(z) ~ N + Percent(), data = dat)\n\n \n\n \n \n\ntinytable_u1d3e8xtavanqxwuqdqi\n\n\n \n\nz\n N\n Percent\n \n\n\n0\n 4\n 57.14\n \n\n1\n 2\n 28.57\n \n\n\n\n\n \n\n\nTo count percentages without missing values, we can exploit the fact that Percent() accepts a denom argument which can be a logical vector:\n\ndatasummary(Factor(z) ~ N + Percent(denom = !is.na(dat$z)), data = dat)\n\n \n\n \n \n\ntinytable_x5g7lf98ftjgx3pl94n4\n\n\n \n\nz\n N\n Percent\n \n\n\n0\n 4\n 66.67\n \n\n1\n 2\n 33.33", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#add-rows", + "href": "vignettes/datasummary.html#add-rows", + "title": "Data Summaries", + "section": "Add rows", + "text": "Add rows\n\nnew_rows <- data.frame('Does',\n 2,\n 'plus',\n 2,\n 'equals',\n 5,\n '?')\ndatasummary(flipper_length_mm + body_mass_g ~ species * (Mean + SD),\n data = penguins,\n add_rows = new_rows)\n\n \n\n \n \n\ntinytable_qg03gd1kumcgoeltrowl\n\n\n \n\n\n \nAdelie\nChinstrap\nGentoo\n\n\n \n Mean\n SD\n Mean\n SD\n Mean\n SD\n \n\n\n\nflipper_length_mm\n 189.95 \n 6.54 \n 195.82 \n 7.13 \n 217.19 \n 6.48 \n \n\nbody_mass_g \n 3700.66\n 458.57\n 3733.09\n 384.34\n 5076.02\n 504.12\n \n\nDoes \n 2.00 \n plus \n 2.00 \n equals\n 5.00 \n ?", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/datasummary.html#add-columns", + "href": "vignettes/datasummary.html#add-columns", + "title": "Data Summaries", + "section": "Add columns", + "text": "Add columns\n\nnew_cols <- data.frame('New Stat' = runif(2))\ndatasummary(flipper_length_mm + body_mass_g ~ species * (Mean + SD),\n data = penguins,\n add_columns = new_cols)\n\n \n\n \n \n\ntinytable_5ul89860ntoihfccw3u6\n\n\n \n\n\n \nAdelie\nChinstrap\nGentoo\n \n\n\n \n Mean\n SD\n Mean\n SD\n Mean\n SD\n New.Stat\n \n\n\n\nflipper_length_mm\n 189.95 \n 6.54 \n 195.82 \n 7.13 \n 217.19 \n 6.48 \n 0.52\n \n\nbody_mass_g \n 3700.66\n 458.57\n 3733.09\n 384.34\n 5076.02\n 504.12\n 0.12", + "crumbs": [ + "Get started", + "Data Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html", + "href": "vignettes/modelsummary.html", + "title": "Model Summaries", + "section": "", + "text": "modelsummary includes a powerful set of utilities to customize the information displayed in your model summary tables. You can easily rename, reorder, subset or omit parameter estimates; choose the set of goodness-of-fit statistics to display; display various “robust” standard errors or confidence intervals; add titles, footnotes, or source notes; insert stars or custom characters to indicate levels of statistical significance; or add rows with supplemental information about your models.\nBefore starting, we set modelsummary to use the tinytable package to draw table, and we set a few CSS properties to make tables more display in a more compact format on this website. This step is optional.\nNow, we download data, fit some models, and summarize them in a table using the modelsummary() function:\nlibrary(modelsummary)\n\nurl <- 'https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv'\ndat <- read.csv(url)\n\nmodels <- list(\n \"OLS 1\" = lm(Donations ~ Literacy + Clergy, data = dat),\n \"Poisson\" = glm(Donations ~ Literacy + Commerce, family = poisson, data = dat),\n \"OLS 2\" = lm(Crime_pers ~ Literacy + Clergy, data = dat)\n)\n\nmodelsummary(models)\n\n \n\n \n \n\ntinytable_jfsnjmbp5o1ordz6e07x\n\n\n \n\n \n OLS 1\n Poisson\n OLS 2\n \n\n\n(Intercept)\n 7948.667 \n 8.241 \n 16259.384 \n \n\n \n (2078.276)\n (0.006) \n (2611.140)\n \n\nLiteracy \n -39.121 \n 0.003 \n 3.680 \n \n\n \n (37.052) \n (0.000) \n (46.552) \n \n\nClergy \n 15.257 \n \n 77.148 \n \n\n \n (25.735) \n \n (32.334) \n \n\nCommerce \n \n 0.011 \n \n \n\n \n \n (0.000) \n \n \n\nNum.Obs. \n 86 \n 86 \n 86 \n \n\nR2 \n 0.020 \n \n 0.065 \n \n\nR2 Adj. \n -0.003 \n \n 0.043 \n \n\nAIC \n 1740.8 \n 274160.8 \n 1780.0 \n \n\nBIC \n 1750.6 \n 274168.2 \n 1789.9 \n \n\nLog.Lik. \n -866.392 \n -137077.401\n -886.021 \n \n\nF \n 0.866 \n 18294.559 \n 2.903 \n \n\nRMSE \n 5740.99 \n 5491.61 \n 7212.97", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#formula", + "href": "vignettes/modelsummary.html#formula", + "title": "Model Summaries", + "section": "Formula", + "text": "Formula\nThe left side of the formula represents the rows and the right side represents the columns. The default formula is term + statistic ~ model:\n\nm <- list(\n lm(mpg ~ hp, data = mtcars),\n lm(mpg ~ hp + drat, data = mtcars))\n\nmodelsummary(m, shape = term + statistic ~ model, gof_map = NA)\n\n \n\n \n \n\ntinytable_vnt7qobsp9k0nssieg01\n\n\n \n\n \n (1)\n (2)\n \n\n\n(Intercept)\n 30.099 \n 10.790 \n \n\n \n (1.634)\n (5.078)\n \n\nhp \n -0.068 \n -0.052 \n \n\n \n (0.010)\n (0.009)\n \n\ndrat \n \n 4.698 \n \n\n \n \n (1.192)\n \n\n\n\n\n \n\n\nWe can display statistics horizontally with:\n\nmodelsummary(m,\n shape = term ~ model + statistic,\n statistic = \"conf.int\",\n gof_map = NA)\n\n \n\n \n \n\ntinytable_rxlcffwy23qh388xn9by\n\n\n \n\n\n \n(1)\n(2)\n\n\n \n Est.\n 2.5 %\n 97.5 %\n Est.\n 2.5 %\n 97.5 %\n \n\n\n\n(Intercept)\n 30.099\n 26.762\n 33.436\n 10.790\n 0.405 \n 21.175\n \n\nhp \n -0.068\n -0.089\n -0.048\n -0.052\n -0.071\n -0.033\n \n\ndrat \n \n \n \n 4.698 \n 2.261 \n 7.135 \n \n\n\n\n\n \n\n\nThe order of terms in the formula determines the order of headers in the table.\n\nmodelsummary(m,\n shape = term ~ statistic + model,\n statistic = \"conf.int\",\n gof_map = NA)\n\n \n\n \n \n\ntinytable_qj145hvhropp2mwczza5\n\n\n \n\n\n \nEst.\n2.5 %\n97.5 %\n\n\n \n (1)\n (2)\n (1)\n (2)\n (1)\n (2)\n \n\n\n\n(Intercept)\n 30.099\n 10.790\n 26.762\n 0.405 \n 33.436\n 21.175\n \n\nhp \n -0.068\n -0.052\n -0.089\n -0.071\n -0.048\n -0.033\n \n\ndrat \n \n 4.698 \n \n 2.261 \n \n 7.135 \n \n\n\n\n\n \n\n\nshape does partial matching and will try to fill-in incomplete formulas:\n\nmodelsummary(m, shape = ~ statistic)\n\nSome models like multinomial logit or GAMLSS produce “grouped” parameter estimates. To display these groups, we can include a group identifier in the shape formula. This group identifier must be one of the column names produced by get_estimates(model). For example, in models produced by nnet::multinom, the group identifier is called “response”:\n\nlibrary(nnet)\n\ndat_multinom <- mtcars\ndat_multinom$cyl <- sprintf(\"Cyl: %s\", dat_multinom$cyl)\n\nmod <- list(\n nnet::multinom(cyl ~ mpg, data = dat_multinom, trace = FALSE),\n nnet::multinom(cyl ~ mpg + drat, data = dat_multinom, trace = FALSE))\n\nget_estimates(mod[[1]])\n\n term estimate std.error conf.level conf.low conf.high statistic df.error p.value response s.value group\n1 (Intercept) 47.252432 34.975171 0.95 -21.2976435 115.8025065 1.351028 Inf 0.17668650 Cyl: 6 2.5 \n2 mpg -2.205418 1.637963 0.95 -5.4157653 1.0049299 -1.346440 Inf 0.17816078 Cyl: 6 2.5 \n3 (Intercept) 72.440246 37.175162 0.95 -0.4217332 145.3022247 1.948619 Inf 0.05134088 Cyl: 8 4.3 \n4 mpg -3.579991 1.774693 0.95 -7.0583242 -0.1016573 -2.017246 Inf 0.04366989 Cyl: 8 4.5 \n\n\nTo summarize the results, we can type:\n\n# modelsummary(mod, shape = term + response ~ statistic)\n\nThe terms of the shape formula above can of course be rearranged to reshape the table. For example:\n\nmodelsummary(mod, shape = model + term ~ response)\n\n \n\n \n \n\ntinytable_nlp5b6raafskihm7d3ee\n\n\n \n\n \n \n Cyl: 6\n Cyl: 8\n \n\n\n(1)\n (Intercept)\n 47.252 \n 72.440 \n \n\n \n \n (34.975)\n (37.175)\n \n\n \n mpg \n -2.205 \n -3.580 \n \n\n \n \n (1.638) \n (1.775) \n \n\n(2)\n (Intercept)\n 89.573 \n 117.971 \n \n\n \n \n (86.884)\n (87.998)\n \n\n \n mpg \n -3.627 \n -4.838 \n \n\n \n \n (3.869) \n (3.915) \n \n\n \n drat \n -3.210 \n -5.028 \n \n\n \n \n (3.810) \n (4.199) \n \n\n\n\n\n \n\n\nWe can combine the term and group identifier columns by inserting an interaction colon : instead of the + in the formula:\n\nlibrary(marginaleffects)\nmod <- glm(am ~ mpg + factor(cyl), family = binomial, data = mtcars)\nmfx <- avg_slopes(mod)\n\nmodelsummary(mfx, shape = term + contrast ~ model)\n\n \n\n \n \n\ntinytable_py6wc0b5ikoyxxjj8z0f\n\n\n \n\n \n \n (1)\n \n\n\ncyl \n 6 - 4\n 0.097 \n \n\n \n \n (0.166)\n \n\n \n 8 - 4\n 0.093 \n \n\n \n \n (0.234)\n \n\nmpg \n dY/dX\n 0.056 \n \n\n \n \n (0.027)\n \n\nNum.Obs.\n \n 32 \n \n\nAIC \n \n 37.4 \n \n\nBIC \n \n 43.3 \n \n\nLog.Lik.\n \n -14.702\n \n\nF \n \n 2.236 \n \n\nRMSE \n \n 0.39 \n \n\n\n\n\n \n\n\n\nmodelsummary(mfx, shape = term : contrast ~ model)\n\n \n\n \n \n\ntinytable_wxzhq2dsmatv9ot2yic8\n\n\n \n\n \n (1)\n \n\n\ncyl 6 - 4\n 0.097 \n \n\n \n (0.166)\n \n\ncyl 8 - 4\n 0.093 \n \n\n \n (0.234)\n \n\nmpg dY/dX\n 0.056 \n \n\n \n (0.027)\n \n\nNum.Obs. \n 32 \n \n\nAIC \n 37.4 \n \n\nBIC \n 43.3 \n \n\nLog.Lik. \n -14.702\n \n\nF \n 2.236 \n \n\nRMSE \n 0.39", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#string-rbind-or-rcollapse-panels-of-models-in-stacked-regression-tables", + "href": "vignettes/modelsummary.html#string-rbind-or-rcollapse-panels-of-models-in-stacked-regression-tables", + "title": "Model Summaries", + "section": "String (“rbind” or “rcollapse”): Panels of models in stacked regression tables", + "text": "String (“rbind” or “rcollapse”): Panels of models in stacked regression tables\nNote: The code in this section requires version 1.3.0 or the development version of modelsummary. See the website for installation instructions.\nThis section shows how to “stack/bind” multiple regression tables on top of one another, to display the results several models side-by-side and top-to-bottom. For example, imagine that we want to present 4 different models, half of which are estimated using a different outcome variable. When using modelsummary, we store models in a list. When using modelsummary with shape=\"rbind\" or shape=\"rbind\", we store models in a list of lists:\n\ngm <- c(\"r.squared\", \"nobs\", \"rmse\")\n\npanels <- list(\n list(\n lm(mpg ~ 1, data = mtcars),\n lm(mpg ~ qsec, data = mtcars)\n ),\n list(\n lm(hp ~ 1, data = mtcars),\n lm(hp ~ qsec, data = mtcars)\n )\n)\n\nmodelsummary(\n panels,\n shape = \"rbind\",\n gof_map = gm)\n\n \n\n \n \n\ntinytable_hpqh2midrcot2aknhdkc\n\n\n \n\n \n (1)\n (2)\n \n\n\n(Intercept)\n 20.091 \n -5.114 \n \n\n \n (1.065) \n (10.030)\n \n\nqsec \n \n 1.412 \n \n\n \n \n (0.559) \n \n\nR2 \n 0.000 \n 0.175 \n \n\nNum.Obs. \n 32 \n 32 \n \n\nRMSE \n 5.93 \n 5.39 \n \n\n(Intercept)\n 146.688 \n 631.704 \n \n\n \n (12.120)\n (88.700)\n \n\nqsec \n \n -27.174 \n \n\n \n \n (4.946) \n \n\nR2 \n 0.000 \n 0.502 \n \n\nNum.Obs. \n 32 \n 32 \n \n\nRMSE \n 67.48 \n 47.64 \n \n\n\n\n\n \n\n\nLike with modelsummary(), we can can name models and panels by naming elements of our nested list:\n\npanels <- list(\n \"Outcome: mpg\" = list(\n \"(I)\" = lm(mpg ~ 1, data = mtcars),\n \"(II)\" = lm(mpg ~ qsec, data = mtcars)\n ),\n \"Outcome: hp\" = list(\n \"(I)\" = lm(hp ~ 1, data = mtcars),\n \"(II)\" = lm(hp ~ qsec, data = mtcars)\n )\n)\n\nmodelsummary(\n panels,\n shape = \"rbind\",\n gof_map = gm)\n\n \n\n \n \n\ntinytable_cflxrrp5071asnnh716w\n\n\n \n\n \n (I)\n (II)\n \n\n\n(Intercept)\n 20.091 \n -5.114 \n \n\n \n (1.065) \n (10.030)\n \n\nqsec \n \n 1.412 \n \n\n \n \n (0.559) \n \n\nR2 \n 0.000 \n 0.175 \n \n\nNum.Obs. \n 32 \n 32 \n \n\nRMSE \n 5.93 \n 5.39 \n \n\n(Intercept)\n 146.688 \n 631.704 \n \n\n \n (12.120)\n (88.700)\n \n\nqsec \n \n -27.174 \n \n\n \n \n (4.946) \n \n\nR2 \n 0.000 \n 0.502 \n \n\nNum.Obs. \n 32 \n 32 \n \n\nRMSE \n 67.48 \n 47.64", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#string-cbind-automatic-spanning-column-labels", + "href": "vignettes/modelsummary.html#string-cbind-automatic-spanning-column-labels", + "title": "Model Summaries", + "section": "String (“cbind”): Automatic spanning column labels", + "text": "String (“cbind”): Automatic spanning column labels\nWhen using the default tinytable backend, we can use a named nested list to automatically add spanning column labels to a table:\n\nmodelsummary(panels, shape = \"cbind\")\n\n \n\n \n \n\ntinytable_tkydpbnalpewpc5p08pp\n\n\n \n\n\n \nOutcome: mpg\nOutcome: hp\n\n\n \n (I)\n (II)\n (I) \n (II) \n \n\n\n\n(Intercept)\n 20.091 \n -5.114 \n 146.688 \n 631.704 \n \n\n \n (1.065) \n (10.030)\n (12.120)\n (88.700)\n \n\nqsec \n \n 1.412 \n \n -27.174 \n \n\n \n \n (0.559) \n \n (4.946) \n \n\nNum.Obs. \n 32 \n 32 \n 32 \n 32 \n \n\nR2 \n 0.000 \n 0.175 \n 0.000 \n 0.502 \n \n\nR2 Adj. \n 0.000 \n 0.148 \n 0.000 \n 0.485 \n \n\nAIC \n 208.8 \n 204.6 \n 364.4 \n 344.1 \n \n\nBIC \n 211.7 \n 209.0 \n 367.3 \n 348.5 \n \n\nLog.Lik. \n -102.378\n -99.294 \n -180.186\n -169.045\n \n\nF \n \n 6.377 \n \n 30.190 \n \n\nRMSE \n 5.93 \n 5.39 \n 67.48 \n 47.64", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#renaming-estimates-and-statistics", + "href": "vignettes/modelsummary.html#renaming-estimates-and-statistics", + "title": "Model Summaries", + "section": "Renaming estimates and statistics", + "text": "Renaming estimates and statistics\nWhen statistics are displayed in different columns, users may want control over the statistic names. To do so, we specify the estimate and statistic as named vectors:\n\nmod <- lm(mpg ~ factor(cyl), mtcars)\n\nmodelsummary(\n mod, \n estimate = c(\"$\\\\hat{\\\\beta}$\" = \"estimate\"),\n statistic = c(\"$\\\\sigma_{\\\\hat{\\\\beta}}$\" = \"std.error\"),\n shape = term ~ model + statistic)\n\n \n\n \n \n\ntinytable_afi912fb28rzir8w63vi\n\n\n \n\n\n \n(1)\n\n\n \n $\\hat{\\beta}$\n $\\sigma_{\\hat{\\beta}}$\n \n\n\n\n(Intercept) \n 26.664 \n 0.972\n \n\nfactor(cyl)6\n -6.921 \n 1.558\n \n\nfactor(cyl)8\n -11.564\n 1.299\n \n\nNum.Obs. \n 32 \n \n \n\nR2 \n 0.732 \n \n \n\nR2 Adj. \n 0.714 \n \n \n\nAIC \n 170.6 \n \n \n\nBIC \n 176.4 \n \n \n\nLog.Lik. \n -81.282\n \n \n\nF \n 39.698 \n \n \n\nRMSE \n 3.07 \n \n \n\n\n\n\n \n\n\nfixest\nThe fixest package offers powerful tools to estimate multiple models using a concise syntax. fixest functions are also convenient because they return named lists of models which are easy to subset and manipulate using standard R functions like grepl.\nFor example, to introduce regressors in stepwise fashion, and to estimate models on different subsets of the data, we can do:\n\n# estimate 4 models\nlibrary(fixest)\nmod <- feols(\n c(hp, mpg) ~ csw(qsec, drat) | gear,\n data = mtcars)\n\n# select models with different outcome variables\npanels <- list(\n \"Miles per gallon\" = mod[grepl(\"mpg\", names(mod))],\n \"Horsepower\" = mod[grepl(\"hp\", names(mod))]\n)\n\nmodelsummary(\n panels,\n shape = \"rcollapse\",\n gof_omit = \"IC|R2\")\n\n \n\n \n \n\ntinytable_d8me8o6lt8zcqu27b1qv\n\n\n \n\n \n (1)\n (2)\n \n\n\nqsec \n 1.436 \n 1.519 \n \n\n \n (0.594) \n (0.529) \n \n\ndrat \n \n 5.765 \n \n\n \n \n (2.381) \n \n\nRMSE \n 4.03 \n 3.67 \n \n\nqsec \n -22.175 \n -22.676 \n \n\n \n (12.762)\n (13.004)\n \n\ndrat \n \n -35.106 \n \n\n \n \n (28.509)\n \n\nRMSE \n 40.45 \n 39.14 \n \n\nNum.Obs. \n 32 \n 32 \n \n\nStd.Errors\n by: gear\n by: gear\n \n\nFE: gear \n X \n X \n \n\n\n\n\n \n\n\nWe can use all the typical extension systems to add information, such as the mean of the dependent variable:\n\nglance_custom.fixest <- function(x, ...) {\n dv <- insight::get_response(x)\n dv <- sprintf(\"%.2f\", mean(dv, na.rm = TRUE))\n data.table::data.table(`Mean of DV` = dv)\n}\n\nmodelsummary(\n panels,\n shape = \"rcollapse\",\n gof_omit = \"IC|R2\")\n\n \n\n \n \n\ntinytable_9yjfdj9np85iv0tdscyi\n\n\n \n\n \n (1)\n (2)\n \n\n\nqsec \n 1.436 \n 1.519 \n \n\n \n (0.594) \n (0.529) \n \n\ndrat \n \n 5.765 \n \n\n \n \n (2.381) \n \n\nRMSE \n 4.03 \n 3.67 \n \n\nMean of DV\n 20.09 \n 20.09 \n \n\nqsec \n -22.175 \n -22.676 \n \n\n \n (12.762)\n (13.004)\n \n\ndrat \n \n -35.106 \n \n\n \n \n (28.509)\n \n\nRMSE \n 40.45 \n 39.14 \n \n\nMean of DV\n 146.69 \n 146.69 \n \n\nNum.Obs. \n 32 \n 32 \n \n\nStd.Errors\n by: gear\n by: gear\n \n\nFE: gear \n X \n X \n \n\n\n\n\n \n\nrm(\"glance_custom.fixest\")", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#reference-categories", + "href": "vignettes/modelsummary.html#reference-categories", + "title": "Model Summaries", + "section": "Reference categories", + "text": "Reference categories\nWhen estimating models with factor regressors, R will typically omit the reference category. We can include an empty row for the reference level automatically by using the include_reference argument. This argument is supplied by the parameters package, which modelsummary uses behind the scenes to extract model estimates. We can supply it directly to modelsummary(), which will then pass the argument forward automatically:\n\ntmp <- transform(mtcars, cyl = factor(cyl))\nmod <- lm(mpg ~ cyl, tmp)\nmodelsummary(mod, include_reference = TRUE)\n\n \n\n \n \n\ntinytable_7cu0clax9cacda2whfwt\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 26.664 \n \n\n \n (0.972)\n \n\ncyl4 \n - \n \n\ncyl6 \n -6.921 \n \n\n \n (1.558)\n \n\ncyl8 \n -11.564\n \n\n \n (1.299)\n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.732 \n \n\nR2 Adj. \n 0.714 \n \n\nAIC \n 170.6 \n \n\nBIC \n 176.4 \n \n\nLog.Lik. \n -81.282\n \n\nF \n 39.698 \n \n\nRMSE \n 3.07", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#standardization", + "href": "vignettes/modelsummary.html#standardization", + "title": "Model Summaries", + "section": "Standardization", + "text": "Standardization\nIn some cases, it is useful to standardize coefficients before reporting them. modelsummary extracts coefficients from model objects using the parameters package, and that package offers several options for standardization: https://easystats.github.io/parameters/reference/model_parameters.default.html\nWe can pass the standardize argument directly to modelsummary or modelplot, and that argument will be forwarded to parameters. For example to refit the model on standardized data and plot the results, we can do:\n\nmod <- lm(mpg ~ hp + am, data = mtcars)\n\nmodelplot(mod, standardize = \"refit\")\n\n\n\n\n\n\n\nCompare to the unstandardized plot:\n\nmodelplot(mod)", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#rmarkdown", + "href": "vignettes/modelsummary.html#rmarkdown", + "title": "Model Summaries", + "section": "Rmarkdown", + "text": "Rmarkdown\nYou can use modelsummary to insert tables into dynamic documents with knitr or Rmarkdown. This minimal .Rmd file can produce tables in PDF, HTML, or RTF documents:\n\nminimal.Rmd\n\nThis .Rmd file shows illustrates how to use table numbering and cross-references to produce PDF documents using bookdown:\n\ncross_references.Rmd\n\nThis .Rmd file shows how to customize tables in PDF and HTML files using gt and kableExtra functions:\n\nappearance.Rmd", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#quarto", + "href": "vignettes/modelsummary.html#quarto", + "title": "Model Summaries", + "section": "Quarto", + "text": "Quarto\nQuarto is an open source publishing system built on top of Pandoc. It was designed as a “successor” to Rmarkdown, and includes useful features for technical writing, such as built-in support for cross-references. modelsummary works automatically with Quarto. This is a minimal document with cross-references which should render automatically to PDF, HTML, and more:\n---\nformat: pdf\ntitle: Example\n---\n\n@tbl-mtcars shows that cars with high horse power get low miles per gallon.\n\n::: {#tbl-mtcars .cell tbl-cap='Horse Powers vs. Miles per Gallon'}\n\n```{.r .cell-code}\nlibrary(modelsummary)\nmod <- lm(mpg ~ hp, mtcars)\nmodelsummary(mod)\n```\n\n::: {.cell-output-display}\n\n```{=html}\n<!DOCTYPE html> \n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>tinytable_l1t6havsgj5f0j9ofag2</title>\n <style>\n.table td.tinytable_css_a91ynn7ukm4oz4fnty0f, .table th.tinytable_css_a91ynn7ukm4oz4fnty0f { border-bottom: solid 0.1em #d3d8dc; }\n.table td.tinytable_css_eh3ubb8rdnzanq420ucz, .table th.tinytable_css_eh3ubb8rdnzanq420ucz { text-align: left; }\n.table td.tinytable_css_9isnj1g1qtz9m0xqpxjg, .table th.tinytable_css_9isnj1g1qtz9m0xqpxjg { text-align: center; }\n.table td.tinytable_css_tfyko8sph08ohxkfufer, .table th.tinytable_css_tfyko8sph08ohxkfufer { border-bottom: solid 0.05em black; }\n </style>\n <script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n <script id=\"MathJax-script\" async src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\"></script>\n <script>\n MathJax = {\n tex: {\n inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n },\n svg: {\n fontCache: 'global'\n }\n };\n </script>\n </head>\n\n <body>\n <div class=\"container\">\n <table class=\"table table-borderless\" id=\"tinytable_l1t6havsgj5f0j9ofag2\" style=\"width: auto; margin-left: auto; margin-right: auto;\" data-quarto-disable-processing='true'>\n <thead>\n \n <tr>\n <th scope=\"col\"> </th>\n <th scope=\"col\">(1)</th>\n </tr>\n </thead>\n \n <tbody>\n <tr>\n <td>(Intercept)</td>\n <td>30.099 </td>\n </tr>\n <tr>\n <td> </td>\n <td>(1.634)</td>\n </tr>\n <tr>\n <td>hp </td>\n <td>-0.068 </td>\n </tr>\n <tr>\n <td> </td>\n <td>(0.010)</td>\n </tr>\n <tr>\n <td>Num.Obs. </td>\n <td>32 </td>\n </tr>\n <tr>\n <td>R2 </td>\n <td>0.602 </td>\n </tr>\n <tr>\n <td>R2 Adj. </td>\n <td>0.589 </td>\n </tr>\n <tr>\n <td>AIC </td>\n <td>181.2 </td>\n </tr>\n <tr>\n <td>BIC </td>\n <td>185.6 </td>\n </tr>\n <tr>\n <td>Log.Lik. </td>\n <td>-87.619</td>\n </tr>\n <tr>\n <td>F </td>\n <td>45.460 </td>\n </tr>\n <tr>\n <td>RMSE </td>\n <td>3.74 </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <script>\n function styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(i, j, css_id) {\n var table = document.getElementById(\"tinytable_l1t6havsgj5f0j9ofag2\");\n table.rows[i].cells[j].classList.add(css_id);\n }\n function insertSpanRow(i, colspan, content) {\n var table = document.getElementById('tinytable_l1t6havsgj5f0j9ofag2');\n var newRow = table.insertRow(i);\n var newCell = newRow.insertCell(0);\n newCell.setAttribute(\"colspan\", colspan);\n // newCell.innerText = content;\n // this may be unsafe, but innerText does not interpret <br>\n newCell.innerHTML = content;\n }\n function spanCell_tinytable_m9ycrvyrvktrqxs7vtgw(i, j, rowspan, colspan) {\n var table = document.getElementById(\"tinytable_l1t6havsgj5f0j9ofag2\");\n const targetRow = table.rows[i];\n const targetCell = targetRow.cells[j];\n for (let r = 0; r < rowspan; r++) {\n // Only start deleting cells to the right for the first row (r == 0)\n if (r === 0) {\n // Delete cells to the right of the target cell in the first row\n for (let c = colspan - 1; c > 0; c--) {\n if (table.rows[i + r].cells[j + c]) {\n table.rows[i + r].deleteCell(j + c);\n }\n }\n }\n // For rows below the first, delete starting from the target column\n if (r > 0) {\n for (let c = colspan - 1; c >= 0; c--) {\n if (table.rows[i + r] && table.rows[i + r].cells[j]) {\n table.rows[i + r].deleteCell(j);\n }\n }\n }\n }\n // Set rowspan and colspan of the target cell\n targetCell.rowSpan = rowspan;\n targetCell.colSpan = colspan;\n }\n\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 0, 'tinytable_css_a91ynn7ukm4oz4fnty0f') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 1, 'tinytable_css_a91ynn7ukm4oz4fnty0f') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(1, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(2, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(3, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(5, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(6, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(7, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(8, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(9, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(10, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(11, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(12, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(1, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(2, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(3, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(5, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(6, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(7, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(8, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(9, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(10, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(11, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(12, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 0, 'tinytable_css_tfyko8sph08ohxkfufer') })\nwindow.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 1, 'tinytable_css_tfyko8sph08ohxkfufer') })\n </script>\n\n </body>\n\n</html>\n```\n\n:::\n:::", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#emacs-org-mode", + "href": "vignettes/modelsummary.html#emacs-org-mode", + "title": "Model Summaries", + "section": "Emacs Org-Mode", + "text": "Emacs Org-Mode\nYou can use modelsummary to insert tables into Emacs Org-Mode documents, which can be exported to a variety of formats, including HTML and PDF (via LaTeX). As with anything Emacs-related, there are many ways to achieve the outcomes you want. Here is one example of an Org-Mode document which can automatically export tables to HTML and PDF without manual tweaks:\n#+PROPERTY: header-args:R :var orgbackend=(prin1-to-string org-export-current-backend)\n#+MACRO: Rtable (eval (concat \"#+header: :results output \" (prin1-to-string org-export-current-backend)))\n\n{{{Rtable}}}\n#+BEGIN_SRC R :exports both\nlibrary(modelsummary)\noptions(modelsummary_factory_default = orgbackend)\n\nmod = lm(hp ~ mpg, data = mtcars)\n\nmodelsummary(mod)\n#+END_SRC\nThe first line tells Org-mode to assign a variable called orgbackend. This variable will be accessible by the R session, and will be equal to “html” or “latex”, depending on the export format.\nThe second line creates an Org macro which we will use to automatically add useful information to the header of source blocks. For instance, when we export to HTML, the macro will expand to :results output html. This tells Org-Mode to insert the last printed output from the R session, and to treat it as raw HTML.\nThe {{Rtable}} call expands the macro to add information to the header of the block that follows.\n#+BEGIN_SRC R :exports both says that we want to print both the original code and the output (:exports results would omit the code, for example).\nFinally, options(modelsummary_factory_default=orgbackend uses the variable we defined to set the default output format. That way, we don’t have to use the output argument every time.\nOne potentially issue to keep in mind is that the code above extracts the printout from the R console. However, when we customize tables with kableExtra or gt functions, those functions do not always return printed raw HTML or LaTeX code. Sometimes, it can be necessary to add a call to cat at the end of a table customization pipeline. For example:\n{{{Rtable}}}\n#+BEGIN_SRC R :exports both\nlibrary(modelsummary)\nlibrary(kableExtra)\n\nmod = lm(hp ~ mpg, data = mtcars)\n\nmodelsummary(mod, output = orgbackend) %>%\n row_spec(1, background = \"pink\") %>%\n cat()\n#+END_SRC", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#collapse-control-variables-into-an-indicator", + "href": "vignettes/modelsummary.html#collapse-control-variables-into-an-indicator", + "title": "Model Summaries", + "section": "Collapse control variables into an indicator", + "text": "Collapse control variables into an indicator\nIn some cases, analysts want to display a single checkmark in their table if a full set of control variables is available. This can easily be achieved with the glance_custom mechanism described in detail in the extension vignette. Here is a simple example:\n\nlibrary(modelsummary)\n\nmod <- list(\n glm(am ~ hp + factor(cyl), data = mtcars, family = binomial),\n lm(mpg ~ hp + factor(cyl) + gear + qsec, data = mtcars)\n)\n\nglance_custom.lm <- function(x, ...) {\n controls <- c(\"gear\", \"qsec\")\n if (all(controls %in% names(coef(x)))) {\n out <- data.frame(Controls = \"✓\")\n } else {\n out <- data.frame(Controls = \"✗\")\n }\n return(out)\n}\n\nglance_custom.glm <- glance_custom.lm\n\nmodelsummary(mod, \"html\", coef_omit = \"qsec|gear\")\n\n \n\n \n \n\ntinytable_ws4114bfqtedd4xsgc6z\n\n\n \n\n \n (1)\n (2)\n \n\n\n(Intercept) \n −2.029 \n 33.178 \n \n\n \n (1.604)\n (13.713)\n \n\nhp \n 0.038 \n −0.057 \n \n\n \n (0.019)\n (0.018) \n \n\nfactor(cyl)6\n −2.874 \n −4.818 \n \n\n \n (1.360)\n (1.805) \n \n\nfactor(cyl)8\n −8.644 \n −4.037 \n \n\n \n (3.423)\n (3.585) \n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 \n \n 0.812 \n \n\nR2 Adj. \n \n 0.776 \n \n\nAIC \n 35.2 \n 165.2 \n \n\nBIC \n 41.1 \n 175.5 \n \n\nLog.Lik. \n −13.602\n −75.598 \n \n\nF \n 2.514 \n 22.526 \n \n\nRMSE \n 0.38 \n 2.57 \n \n\nControls \n ✗ \n ✓ \n \n\n\n\n\n \n\n\nReturn to nomal:\n\nrm(list = c(\"glance_custom.glm\", \"glance_custom.lm\"))", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#subgroup-estimation-with-nest_by", + "href": "vignettes/modelsummary.html#subgroup-estimation-with-nest_by", + "title": "Model Summaries", + "section": "Subgroup estimation with nest_by\n", + "text": "Subgroup estimation with nest_by\n\nSometimes, it is useful to estimate multiple regression models on subsets of the data. To do this efficiently, we can use the nest_by function from the dplyr package. Then, estimate the models with lm, extract them and name them with pull, and finally summarize them with modelsummary:\n\nlibrary(tidyverse)\n\nmtcars %>%\n nest_by(cyl) %>%\n mutate(models = list(lm(mpg ~ hp, data))) %>%\n pull(models, name = cyl) %>%\n modelsummary\n\n \n\n \n \n\ntinytable_w4yvlonh9rkvo0nj674f\n\n\n \n\n \n 4\n 6\n 8\n \n\n\n(Intercept)\n 35.983 \n 20.674 \n 18.080 \n \n\n \n (5.201)\n (3.304)\n (2.988)\n \n\nhp \n -0.113 \n -0.008 \n -0.014 \n \n\n \n (0.061)\n (0.027)\n (0.014)\n \n\nNum.Obs. \n 11 \n 7 \n 14 \n \n\nR2 \n 0.274 \n 0.016 \n 0.080 \n \n\nR2 Adj. \n 0.193 \n -0.181 \n 0.004 \n \n\nAIC \n 65.8 \n 29.9 \n 69.8 \n \n\nBIC \n 67.0 \n 29.7 \n 71.8 \n \n\nLog.Lik. \n -29.891\n -11.954\n -31.920\n \n\nRMSE \n 3.66 \n 1.33 \n 2.37", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#bootstrap", + "href": "vignettes/modelsummary.html#bootstrap", + "title": "Model Summaries", + "section": "Bootstrap", + "text": "Bootstrap\nUsers often want to use estimates or standard errors that have been obtained using a custom strategy. To achieve this in an automated and replicable way, it can be useful to use the tidy_custom strategy described above in the “Cutomizing Existing Models” section.\nFor example, we can use the modelr package to draw 500 resamples of a dataset, and compute bootstrap standard errors by taking the standard deviation of estimates computed in all of those resampled datasets. To do this, we defined tidy_custom.lm function that will automatically bootstrap any lm model supplied to modelsummary, and replace the values in the table automatically.\nNote that the tidy_custom_lm returns a data.frame with 3 columns: term, estimate, and std.error:\n\nlibrary(\"broom\")\nlibrary(\"tidyverse\")\nlibrary(\"modelr\")\n\ntidy_custom.lm <- function(x, ...) {\n # extract data from the model\n model.frame(x) %>%\n # draw 500 bootstrap resamples\n modelr::bootstrap(n = 500) %>%\n # estimate the model 500 times\n mutate(results = map(strap, ~ update(x, data = .))) %>%\n # extract results using `broom::tidy`\n mutate(results = map(results, tidy)) %>%\n # unnest and summarize\n unnest(results) %>%\n group_by(term) %>%\n summarize(std.error = sd(estimate),\n estimate = mean(estimate))\n}\n\nmod = list(\n lm(hp ~ mpg, mtcars) ,\n lm(hp ~ mpg + drat, mtcars))\n\nmodelsummary(mod)\n\n \n\n \n \n\ntinytable_dhfo3oc3ab7j90rherha\n\n\n \n\n \n (1)\n (2)\n \n\n\n(Intercept)\n 327.375 \n 283.415 \n \n\n \n (31.272)\n (46.284)\n \n\nmpg \n -9.019 \n -10.036 \n \n\n \n (1.442) \n (2.301) \n \n\ndrat \n \n 17.680 \n \n\n \n \n (21.958)\n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 \n 0.602 \n 0.614 \n \n\nR2 Adj. \n 0.589 \n 0.588 \n \n\nAIC \n 336.9 \n 337.9 \n \n\nBIC \n 341.3 \n 343.7 \n \n\nLog.Lik. \n -165.428\n -164.940\n \n\nF \n 45.460 \n 23.100 \n \n\nRMSE \n 42.55 \n 41.91", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#fixest-fixed-effects-and-instrumental-variable-regression", + "href": "vignettes/modelsummary.html#fixest-fixed-effects-and-instrumental-variable-regression", + "title": "Model Summaries", + "section": "\nfixest: Fixed effects and instrumental variable regression", + "text": "fixest: Fixed effects and instrumental variable regression\nOne common use-case for glance_custom is to include additional goodness-of-fit statistics. For example, in an instrumental variable estimation computed by the fixest package, we may want to include an IV-Wald statistic for the first-stage regression of each endogenous regressor:\n\nlibrary(fixest)\nlibrary(tidyverse)\n\n# create a toy dataset\nbase <- iris\nnames(base) <- c(\"y\", \"x1\", \"x_endo_1\", \"x_inst_1\", \"fe\")\nbase$x_inst_2 <- 0.2 * base$y + 0.2 * base$x_endo_1 + rnorm(150, sd = 0.5)\nbase$x_endo_2 <- 0.2 * base$y - 0.2 * base$x_inst_1 + rnorm(150, sd = 0.5)\n\n# estimate an instrumental variable model\nmod <- feols(y ~ x1 | fe | x_endo_1 + x_endo_2 ~ x_inst_1 + x_inst_2, base)\n\n# custom extractor function returns a one-row data.frame (or tibble)\nglance_custom.fixest <- function(x) {\n tibble(\n \"Wald (x_endo_1)\" = fitstat(x, \"ivwald\")[[1]]$stat,\n \"Wald (x_endo_2)\" = fitstat(x, \"ivwald\")[[2]]$stat\n )\n}\n\n# draw table\nmodelsummary(mod)\n\n \n\n \n \n\ntinytable_ijejn7mhkwpr9dsmkson\n\n\n \n\n \n (1)\n \n\n\nfit_x_endo_1 \n 2.388 \n \n\n \n (26.738) \n \n\nfit_x_endo_2 \n 20.854 \n \n\n \n (317.291) \n \n\nx1 \n 1.398 \n \n\n \n (16.551) \n \n\nNum.Obs. \n 150 \n \n\nR2 \n -188.225 \n \n\nR2 Adj. \n -194.795 \n \n\nR2 Within \n -495.270 \n \n\nR2 Within Adj. \n -505.609 \n \n\nAIC \n 1166.5 \n \n\nBIC \n 1184.6 \n \n\nRMSE \n 11.35 \n \n\nStd.Errors \n by: fe \n \n\nFE: fe \n X \n \n\nWald (x_endo_1)\n 42.2275700153234 \n \n\nWald (x_endo_2)\n 0.0911469615478482\n \n\n\n\n\n \n\n\n\nrm(\"glance_custom.fixest\")", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#multiple-imputation", + "href": "vignettes/modelsummary.html#multiple-imputation", + "title": "Model Summaries", + "section": "Multiple imputation", + "text": "Multiple imputation\nmodelsummary can pool and display analyses on several datasets imputed using the mice or Amelia packages. This code illustrates how:\n\nlibrary(mice)\nlibrary(Amelia)\n\n# Download data from `Rdatasets`\nurl <- 'https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv'\ndat <- read.csv(url)[, c('Clergy', 'Commerce', 'Literacy')]\n\n# Insert missing values\ndat$Clergy[sample(1:nrow(dat), 10)] <- NA\ndat$Commerce[sample(1:nrow(dat), 10)] <- NA\ndat$Literacy[sample(1:nrow(dat), 10)] <- NA\n\n# Impute with `mice` and `Amelia`\ndat_mice <- mice(dat, m = 5, printFlag = FALSE)\ndat_amelia <- amelia(dat, m = 5, p2s = 0)$imputations\n\n# Estimate models\nmod <- list()\nmod[['Listwise deletion']] <- lm(Clergy ~ Literacy + Commerce, dat)\nmod[['Mice']] <- with(dat_mice, lm(Clergy ~ Literacy + Commerce)) \nmod[['Amelia']] <- lapply(dat_amelia, function(x) lm(Clergy ~ Literacy + Commerce, x))\n\n# Pool results\nmod[['Mice']] <- mice::pool(mod[['Mice']])\nmod[['Amelia']] <- mice::pool(mod[['Amelia']])\n\n# Summarize\nmodelsummary(mod)\n\n \n\n \n \n\ntinytable_ybkahyi00wojw7ksrmch\n\n\n \n\n \n Listwise deletion\n Mice\n Amelia\n \n\n\n(Intercept)\n 84.971 \n 78.743 \n 76.645 \n \n\n \n (14.073)\n (12.630)\n (13.559)\n \n\nLiteracy \n -0.565 \n -0.487 \n -0.476 \n \n\n \n (0.224) \n (0.203) \n (0.199) \n \n\nCommerce \n -0.423 \n -0.387 \n -0.352 \n \n\n \n (0.162) \n (0.133) \n (0.153) \n \n\nNum.Obs. \n 60 \n 86 \n 86 \n \n\nNum.Imp. \n \n 5 \n 5 \n \n\nR2 \n 0.131 \n 0.118 \n 0.098 \n \n\nR2 Adj. \n 0.101 \n 0.096 \n 0.076 \n \n\nAIC \n 559.8 \n \n \n \n\nBIC \n 568.2 \n \n \n \n\nLog.Lik. \n -275.909\n \n \n \n\nRMSE \n 24.04", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#stack-overflow-is-useful", + "href": "vignettes/modelsummary.html#stack-overflow-is-useful", + "title": "Model Summaries", + "section": "Stack Overflow is useful", + "text": "Stack Overflow is useful\n\nStandardized coefficients\nRow group labels\nCustomizing Word tables\nHow to add p values to datasummary_correlation", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#where-can-i-get-help", + "href": "vignettes/modelsummary.html#where-can-i-get-help", + "title": "Model Summaries", + "section": "Where can I get help?", + "text": "Where can I get help?\nFirst, please read the documentation in ?modelsummary and on the modelsummary website. The website includes dozens of worked examples and a lot of detailed explanation.\nSecond, try to use the [modelsummary] tag on StackOverflow.\nThird, if you think you found a bug or have a feature request, please file it on the Github issue tracker:", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#how-can-i-add-or-modify-statistics-in-a-table", + "href": "vignettes/modelsummary.html#how-can-i-add-or-modify-statistics-in-a-table", + "title": "Model Summaries", + "section": "How can I add or modify statistics in a table?", + "text": "How can I add or modify statistics in a table?\nSee the detailed documentation in the “Adding and Customizing Models” section of the modelsummary website.", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#how-does-modelsummary-extract-estimates-and-goodness-of-fit-statistics", + "href": "vignettes/modelsummary.html#how-does-modelsummary-extract-estimates-and-goodness-of-fit-statistics", + "title": "Model Summaries", + "section": "How does modelsummary extract estimates and goodness-of-fit statistics?", + "text": "How does modelsummary extract estimates and goodness-of-fit statistics?\nA modelsummary table is divided in two parts: “Estimates” (top of the table) and “Goodness-of-fit” (bottom of the table). To populate those two parts, modelsummary tries using the broom, parameters and performance packages in sequence.\nEstimates:\n\nTry the broom::tidy function to see if that package supports this model type, or if the user defined a custom tidy function in their global environment. If this fails…\nTry the parameters::model_parameters function to see if the parameters package supports this model type.\n\nGoodness-of-fit:\n\nTry the performance::model_performance function to see if the performance package supports this model type.\nTry the broom::glance function to see if that package supports this model type, or if the user defined a custom glance function in their global environment. If this fails…\n\nYou can change the order in which those steps are executed by setting a global option:\n\n# tidymodels: broom \noptions(modelsummary_get = \"broom\")\n\n# easystats: performance + parameters\noptions(modelsummary_get = \"easystats\")\n\nIf all of this fails, modelsummary will return an error message.\nIf you have problems with a model object, you can often diagnose the problem by running the following commands from a clean R session:\n# see if parameters and performance support your model type\nlibrary(parameters)\nlibrary(performance)\nmodel_parameters(model)\nmodel_performance(model)\n\n# see if broom supports your model type\nlibrary(broom)\ntidy(model)\nglance(model)\n\n# see if broom.mixed supports your model type\nlibrary(broom.mixed)\ntidy(model)\nglance(model)\nIf none of these options work, you can create your own tidy and glance methods, as described in the Adding new models section.\nIf one of the extractor functions does not work well or takes too long to process, you can define a new “custom” model class and choose your own extractors, as described in the Adding new models section.", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#how-can-i-speed-up-modelsummary", + "href": "vignettes/modelsummary.html#how-can-i-speed-up-modelsummary", + "title": "Model Summaries", + "section": "How can I speed up modelsummary?", + "text": "How can I speed up modelsummary?\nThe modelsummary function, by itself, is not slow: it should only take a couple seconds to produce a table in any output format. However, sometimes it can be computationally expensive (and long) to extract estimates and to compute goodness-of-fit statistics for your model.\nThe main options to speed up modelsummary are:\n\nSet gof_map=NA to avoid computing expensive goodness-of-fit statistics.\nUse the easystats extractor functions and the metrics argument to avoid computing expensive statistics (see below for an example).\nUse parallel computation if you are summarizing multiple models. See the “Parallel computation” section in the ?modelsummary documentation.\n\nTo diagnose the slowdown and find the bottleneck, you can try to benchmark the various extractor functions:\n\nlibrary(tictoc)\n\ndata(trade)\nmod <- lm(mpg ~ hp + drat, mtcars)\n\ntic(\"tidy\")\nx <- broom::tidy(mod)\ntoc()\n\ntidy: 0.006 sec elapsed\n\ntic(\"glance\")\nx <- broom::glance(mod)\ntoc()\n\nglance: 0.01 sec elapsed\n\ntic(\"parameters\")\nx <- parameters::parameters(mod)\ntoc()\n\nparameters: 0.038 sec elapsed\n\ntic(\"performance\")\nx <- performance::performance(mod)\ntoc()\n\nperformance: 0.016 sec elapsed\n\n\nIn my experience, the main bottleneck tends to be computing goodness-of-fit statistics. The performance extractor allows users to specify a metrics argument to select a subset of GOF to include. Using this can speedup things considerably.\nWe call modelsummary with the metrics argument:\n\nmodelsummary(mod, metrics = \"rmse\")\n\n \n\n \n \n\ntinytable_qw56knvavu3hbunozv92\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 10.790 \n \n\n \n (5.078)\n \n\nhp \n -0.052 \n \n\n \n (0.009)\n \n\ndrat \n 4.698 \n \n\n \n (1.192)\n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.741 \n \n\nR2 Adj. \n 0.723 \n \n\nAIC \n 169.5 \n \n\nBIC \n 175.4 \n \n\nLog.Lik. \n -80.752\n \n\nF \n 41.522", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#escaped-latex-characters", + "href": "vignettes/modelsummary.html#escaped-latex-characters", + "title": "Model Summaries", + "section": "Escaped LaTeX characters", + "text": "Escaped LaTeX characters\nSometimes, users want to include raw LaTeX commands in their tables, such as coefficient names including math mode: Apple $\\times$ Orange. The result of these attempts is often a weird string such as: \\$\\textbackslash{}times\\$ instead of proper LaTeX-rendered characters.\nThe source of the problem is that kableExtra, default table-making package in modelsummary, automatically escapes weird characters to make sure that your tables compile properly in LaTeX. To avoid this, we need to pass the escape=FALSE to modelsummary:\n\nmodelsummary(mod, escape = FALSE)", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/modelsummary.html#bayesian-models", + "href": "vignettes/modelsummary.html#bayesian-models", + "title": "Model Summaries", + "section": "Bayesian models", + "text": "Bayesian models\nMany bayesian models are supported out-of-the-box, including those produced by the rstanarm and brms packages. The statistics available for bayesian models are slightly different than those available for most frequentist models. Users can call get_estimates to see what is available:\n\nlibrary(rstanarm)\n\nThis is rstanarm version 2.32.1\n\n\n- See https://mc-stan.org/rstanarm/articles/priors for changes to default priors!\n\n\n- Default priors may change, so it's safest to specify priors, even if equivalent to the defaults.\n\n\n- For execution on a local, multicore CPU with excess RAM we recommend calling\n\n\n options(mc.cores = parallel::detectCores())\n\n\n\nAttaching package: 'rstanarm'\n\n\nThe following object is masked from 'package:fixest':\n\n se\n\nmod <- stan_glm(am ~ hp + drat, data = mtcars)\n\n\nget_estimates(mod)\n\n term estimate mad conf.level conf.low conf.high prior.distribution prior.location prior.scale group std.error statistic p.value\n1 (Intercept) -2.2236089637 0.589441345 0.95 -3.436529813 -1.041750262 normal 0.40625 1.24747729 NA NA NA\n2 hp 0.0007253039 0.001020979 0.95 -0.001507643 0.002869693 normal 0.00000 0.01819465 NA NA NA\n3 drat 0.7030393239 0.140505922 0.95 0.421813308 0.982043203 normal 0.00000 2.33313429 NA NA NA\n\n\nThis shows that there is no std.error column, but that there is a mad statistic (mean absolute deviation). So we can do:\n\nmodelsummary(mod, statistic = \"mad\")\n\nWarning: \n`modelsummary` uses the `performance` package to extract goodness-of-fit\nstatistics from models of this class. You can specify the statistics you wish\nto compute by supplying a `metrics` argument to `modelsummary`, which will then\npush it forward to `performance`. Acceptable values are: \"all\", \"common\",\n\"none\", or a character vector of metrics names. For example: `modelsummary(mod,\nmetrics = c(\"RMSE\", \"R2\")` Note that some metrics are computationally\nexpensive. See `?performance::performance` for details.\n This warning appears once per session.\n\n\n \n\n \n \n\ntinytable_srx0i5lzhxrae2lelvc6\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n -2.224 \n \n\n \n (0.589)\n \n\nhp \n 0.001 \n \n\n \n (0.001)\n \n\ndrat \n 0.703 \n \n\n \n (0.141)\n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.498 \n \n\nR2 Adj. \n 0.440 \n \n\nLog.Lik. \n -12.047\n \n\nELPD \n -15.0 \n \n\nELPD s.e. \n 3.1 \n \n\nLOOIC \n 30.1 \n \n\nLOOIC s.e. \n 6.2 \n \n\nWAIC \n 29.8 \n \n\nRMSE \n 0.34 \n \n\n\n\n\n \n\n\nAs noted in the modelsummary() documentation, model results are extracted using the parameters package. Users can pass additional arguments to modelsummary(), which will then push forward those arguments to the parameters::parameters function to change the results. For example, the parameters documentation for bayesian models shows that there is a centrality argument, which allows users to report the mean and standard deviation of the posterior distribution, instead of the median and MAD:\n\nget_estimates(mod, centrality = \"mean\")\n\n term estimate std.dev conf.level conf.low conf.high prior.distribution prior.location prior.scale group std.error statistic p.value\n1 (Intercept) -2.2221087678 0.60877621 0.95 -3.436529813 -1.041750262 normal 0.40625 1.24747729 NA NA NA\n2 hp 0.0007113946 0.00107747 0.95 -0.001507643 0.002869693 normal 0.00000 0.01819465 NA NA NA\n3 drat 0.7020620279 0.14233319 0.95 0.421813308 0.982043203 normal 0.00000 2.33313429 NA NA NA\n\nmodelsummary(mod, statistic = \"std.dev\", centrality = \"mean\")\n\n \n\n \n \n\ntinytable_k132niqpac5dwttdshxq\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n -2.222 \n \n\n \n (0.609)\n \n\nhp \n 0.001 \n \n\n \n (0.001)\n \n\ndrat \n 0.702 \n \n\n \n (0.142)\n \n\nNum.Obs. \n 32 \n \n\nR2 \n 0.498 \n \n\nR2 Adj. \n 0.440 \n \n\nLog.Lik. \n -12.047\n \n\nELPD \n -15.0 \n \n\nELPD s.e. \n 3.1 \n \n\nLOOIC \n 30.1 \n \n\nLOOIC s.e. \n 6.2 \n \n\nWAIC \n 29.8 \n \n\nRMSE \n 0.34 \n \n\n\n\n\n \n\n\nWe can also get additional test statistics using the test argument:\n\nget_estimates(mod, test = c(\"pd\", \"rope\"))\n\n term estimate mad conf.level conf.low conf.high pd rope.percentage prior.distribution prior.location prior.scale group std.error statistic p.value\n1 (Intercept) -2.2236089637 0.589441345 0.95 -3.436529813 -1.041750262 0.99925 0 normal 0.40625 1.24747729 NA NA NA\n2 hp 0.0007253039 0.001020979 0.95 -0.001507643 0.002869693 0.75550 1 normal 0.00000 0.01819465 NA NA NA\n3 drat 0.7030393239 0.140505922 0.95 0.421813308 0.982043203 1.00000 0 normal 0.00000 2.33313429 NA NA NA", + "crumbs": [ + "Get started", + "Model Summaries" + ] + }, + { + "objectID": "vignettes/get_started.html", + "href": "vignettes/get_started.html", + "title": "Getting started", + "section": "", + "text": "To begin, load the modelsummary package and download data from the Rdatasets archive:\n\nlibrary(modelsummary)\nlibrary(tinytable)\n\nurl <- 'https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv'\ndat <- read.csv(url) \ndat$Small <- dat$Pop1831 > median(dat$Pop1831)\ndat <- dat[, \n c(\"Donations\", \"Literacy\", \"Commerce\", \"Crime_pers\", \"Crime_prop\", \"Clergy\", \"Small\")\n]\n\nData Summaries\nQuick overview of the data:\n\ndatasummary_skim(dat)\n\nWarning: The `replace_na` argument was renamed `replace`.\n\n\n \n\n \n \n\ntinytable_qp4vhdm4xbnlhue8co0a\n\n\n \n\n \n Unique\n Missing Pct.\n Mean\n SD\n Min\n Median\n Max\n Histogram\n \n\n\nDonations\n 85\n 0\n 7075.5\n 5834.6\n 1246.0\n 5020.0\n 37015.0\n \n \n\nLiteracy\n 50\n 0\n 39.3\n 17.4\n 12.0\n 38.0\n 74.0\n \n \n\nCommerce\n 84\n 0\n 42.8\n 25.0\n 1.0\n 42.5\n 86.0\n \n \n\nCrime_pers\n 85\n 0\n 19754.4\n 7504.7\n 2199.0\n 18748.5\n 37014.0\n \n \n\nCrime_prop\n 86\n 0\n 7843.1\n 3051.4\n 1368.0\n 7595.0\n 20235.0\n \n \n\nClergy\n 85\n 0\n 43.4\n 25.0\n 1.0\n 43.5\n 86.0\n \n \n\nSmall\n N\n %\n \n \n \n \n \n \n \n\nFALSE\n 43\n 50.0\n \n \n \n \n \n \n \n\nTRUE\n 43\n 50.0\n \n \n \n \n \n \n \n\n\n\n\n \n\n\nBalance table (aka “Table 1”) with differences in means by subgroups:\n\ndatasummary_balance(~Small, dat)\n\n \n\n \n \n\ntinytable_4lo67dbx8d3w2zifim0h\n\n\n \n\n\n \nFALSE (N=43)\nTRUE (N=43)\n \n \n\n\n \n Mean\n Std. Dev.\n Mean\n Std. Dev.\n Diff. in Means\n Std. Error\n \n\n\n\nDonations \n 7258.5 \n 6194.1\n 6892.6 \n 5519.0\n -365.9 \n 1265.2\n \n\nLiteracy \n 37.9 \n 19.1 \n 40.6 \n 15.6 \n 2.7 \n 3.8 \n \n\nCommerce \n 42.7 \n 24.6 \n 43.0 \n 25.7 \n 0.3 \n 5.4 \n \n\nCrime_pers\n 18040.6\n 7638.4\n 21468.2\n 7044.3\n 3427.7 \n 1584.6\n \n\nCrime_prop\n 8422.5 \n 3406.7\n 7263.7 \n 2559.3\n -1158.8\n 649.8 \n \n\nClergy \n 39.1 \n 26.7 \n 47.7 \n 22.7 \n 8.6 \n 5.3 \n \n\n\n\n\n \n\n\nCorrelation table:\n\ndatasummary_correlation(dat)\n\n \n\n \n \n\ntinytable_eihf2074ydx9ewxee9ph\n\n\n \n\n \n Donations\n Literacy\n Commerce\n Crime_pers\n Crime_prop\n Clergy\n \n\n\nDonations \n 1 \n . \n . \n . \n . \n .\n \n\nLiteracy \n -.13\n 1 \n . \n . \n . \n .\n \n\nCommerce \n .30 \n -.58\n 1 \n . \n . \n .\n \n\nCrime_pers\n -.04\n -.04\n .05 \n 1 \n . \n .\n \n\nCrime_prop\n -.13\n -.37\n .41 \n .27\n 1 \n .\n \n\nClergy \n .09 \n -.17\n -.12\n .26\n -.07\n 1\n \n\n\n\n\n \n\n\nTwo variables and two statistics, nested in subgroups:\n\ndatasummary(Literacy + Commerce ~ Small * (mean + sd), dat)\n\n \n\n \n \n\ntinytable_jgn2kgdkuhvx18wmu5ql\n\n\n \n\n\n \nFALSE\nTRUE\n\n\n \n mean\n sd\n mean\n sd\n \n\n\n\nLiteracy\n 37.88\n 19.08\n 40.63\n 15.57\n \n\nCommerce\n 42.65\n 24.59\n 42.95\n 25.75\n \n\n\n\n\n \n\n\nModel Summaries\nEstimate a linear model and display the results:\n\nmod <- lm(Donations ~ Crime_prop, data = dat)\n\nmodelsummary(mod)\n\n \n\n \n \n\ntinytable_fi5e5k990wwpf66l5pwc\n\n\n \n\n \n (1)\n \n\n\n(Intercept)\n 9065.287 \n \n\n \n (1738.926)\n \n\nCrime_prop \n -0.254 \n \n\n \n (0.207) \n \n\nNum.Obs. \n 86 \n \n\nR2 \n 0.018 \n \n\nR2 Adj. \n 0.006 \n \n\nAIC \n 1739.0 \n \n\nBIC \n 1746.4 \n \n\nLog.Lik. \n -866.516 \n \n\nF \n 1.505 \n \n\nRMSE \n 5749.29 \n \n\n\n\n\n \n\n\nNow estimate five regression models, display the results side-by-side, and use the group_tt() function from the tinytable package to add column labels:\n\nlibrary(tinytable)\n\nmodels <- list(\n \"I\" = lm(Donations ~ Literacy + Clergy, data = dat),\n \"II\" = lm(Crime_pers ~ Literacy + Clergy, data = dat),\n \"III\" = lm(Crime_prop ~ Literacy + Clergy, data = dat),\n \"IV\" = glm(Crime_pers ~ Literacy + Commerce, family = poisson, data = dat),\n \"V\" = glm(Donations ~ Literacy + Commerce, family = poisson, data = dat)\n)\n\nmodelsummary(models, stars = TRUE, gof_omit = \"IC|Adj|F|RMSE|Log\") |>\n group_tt(j = list(\"Linear\" = 2:4, \"Poisson\" = 5:6))\n\n \n\n \n \n\ntinytable_h0rz3rj7doax5ogrzmu6\n\n\n \n\n\n \nLinear\nPoisson\n\n\n \n I\n II\n III\n IV\n V\n \n\n+ p \n\n\n(Intercept)\n 7948.667***\n 16259.384***\n 11243.544***\n 9.876***\n 8.241***\n \n\n \n (2078.276) \n (2611.140) \n (1011.240) \n (0.003) \n (0.006) \n \n\nLiteracy \n -39.121 \n 3.680 \n -68.507*** \n 0.000***\n 0.003***\n \n\n \n (37.052) \n (46.552) \n (18.029) \n (0.000) \n (0.000) \n \n\nClergy \n 15.257 \n 77.148* \n -16.376 \n \n \n \n\n \n (25.735) \n (32.334) \n (12.522) \n \n \n \n\nCommerce \n \n \n \n 0.001***\n 0.011***\n \n\n \n \n \n \n (0.000) \n (0.000) \n \n\nNum.Obs. \n 86 \n 86 \n 86 \n 86 \n 86 \n \n\nR2 \n 0.020 \n 0.065 \n 0.152 \n \n \n \n\n\n\n\n \n\n\nNow, save it to a Microsoft Word document:\n\nmodelsummary(models, output = \"table.docx\")\n\nAnd draw a coefficient plot:\n\nols <- models[1:3]\nmodelplot(ols, coef_omit = \"Intercept\")", + "crumbs": [ + "Get started", + "Getting started" + ] + }, + { + "objectID": "vignettes/modelplot.html", + "href": "vignettes/modelplot.html", + "title": "Model Plots", + "section": "", + "text": "modelplot is a function from the modelsummary package. It allows you to plot model estimates and confidence intervals. It makes it easy to subset, rename, reorder, and customize plots using same mechanics as in modelsummary.\nTo illustrate how the function works, we fit a linear model to data about the Palmer Penguins:\nurl <- 'https://vincentarelbundock.github.io/Rdatasets/csv/palmerpenguins/penguins.csv'\ndat <- read.csv(url)\n\n# rescale mm -> cm\ndat$bill_length_cm <- dat$bill_length_mm / 10\ndat$flipper_length_cm <- dat$flipper_length_mm / 10\n\nmod <- lm(bill_length_cm ~ flipper_length_cm + species, data = dat)\nThen, we load the modelsummary library and call modelplot:\nlibrary(modelsummary)\n\nmodelplot(mod)", + "crumbs": [ + "Get started", + "Model Plots" + ] + }, + { + "objectID": "vignettes/modelplot.html#conditional-colors-and-shape", + "href": "vignettes/modelplot.html#conditional-colors-and-shape", + "title": "Model Plots", + "section": "Conditional colors and shape", + "text": "Conditional colors and shape\nNote: This section requires a version of modelsummary greater than 1.2.0 or the development version.\nIn a very nice Stack Overflow answer, Allan Cameron shows how we can use the aes() function from ggplot2 to add conditional aesthetics. For example, if we want to display statistically significant coefficients in a different color:\n\nlibrary(ggplot2)\nmod <- lm(hp ~ factor(gear) + factor(cyl), data = mtcars)\n\nmodelplot(mod, coef_rename = TRUE) +\n aes(color = ifelse(p.value < 0.001, \"Significant\", \"Not significant\")) +\n scale_color_manual(values = c(\"grey\", \"black\"))", + "crumbs": [ + "Get started", + "Model Plots" + ] + }, + { + "objectID": "vignettes/modelplot.html#example-using-facets-to-compare-models", + "href": "vignettes/modelplot.html#example-using-facets-to-compare-models", + "title": "Model Plots", + "section": "Example: Using facets to compare models", + "text": "Example: Using facets to compare models\nCustomizing plots with ggplot2 makes modelplot very flexible. For example, imagine you want to compare the coefficients of three models with different dependent variables. First, we load the packages and estimate our models:\n\nlibrary(ggplot2)\nlibrary(modelsummary)\n\nmodels <- list(\n lm(vs ~ carb + mpg + cyl, data = mtcars),\n lm(disp ~ carb + mpg + cyl, data = mtcars),\n lm(hp ~ carb + mpg + cyl, data = mtcars))\n\nThen, we use the dvnames function to rename our list with names matching the the dependent variable in each model:\n\nmodels <- dvnames(models)\n\nBy calling modelplot with the draw=FALSE argument, we see the raw data used to draw the plot. Here, we see that there is a model column:\n\nmodelplot(models, draw = FALSE)\n\n term model estimate std.error conf.low conf.high p.value\n1 (Intercept) vs 2.41742511 0.67622094 1.03224931 3.80260091 1.296718e-03\n5 (Intercept) disp 112.57276339 114.86315481 -122.71374324 347.85927003 3.354494e-01\n9 (Intercept) hp -10.56116383 68.75946117 -151.40853516 130.28620751 8.790301e-01\n2 carb vs -0.06945116 0.03943402 -0.15022810 0.01132577 8.912324e-02\n6 carb disp -12.30144724 6.69827859 -26.02224894 1.41935446 7.692105e-02\n10 carb hp 17.75593287 4.00972816 9.54237706 25.96948867 1.320972e-04\n3 mpg vs -0.01513960 0.01716410 -0.05029868 0.02001947 3.852593e-01\n7 mpg disp -7.14964651 2.91550156 -13.12178072 -1.17751230 2.068858e-02\n11 mpg hp -1.00486469 1.74527956 -4.57990780 2.57017842 5.693755e-01\n4 cyl vs -0.23926135 0.05687969 -0.35577411 -0.12274859 2.410214e-04\n8 cyl disp 47.90105842 9.66160634 28.11015499 67.69196184 3.111898e-05\n12 cyl hp 20.60581208 5.78363747 8.75856779 32.45305638 1.338485e-03\n\n\nFinally, we use the model column as our identifier in ggplot2’s facet_grid command to display models side by side:\n\nmodelplot(models, color = \"black\") + facet_grid(~model)", + "crumbs": [ + "Get started", + "Model Plots" + ] + }, + { + "objectID": "vignettes/appearance.html", + "href": "vignettes/appearance.html", + "title": "Themes and Styles", + "section": "", + "text": "To customize the appearance of tables, modelsummary supports five of the most popular table-making packages:\nUsers are encouraged to visit these websites to determine which package suits their needs best.\nTo create customized tables, we proceed as follows:\nTo illustrate, we download data from the Rdatasets repository and we estimate 5 models:\nlibrary(modelsummary)\n\nurl <- \"https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv\"\ndat <- read.csv(url, na.strings = \"\")\n\nmodels <- list(\n I = lm(Donations ~ Literacy, data = dat),\n II = lm(Crime_pers ~ Literacy, data = dat),\n III = lm(Crime_prop ~ Literacy + Clergy, data = dat),\n IV = glm(Crime_pers ~ Literacy + Clergy, family = poisson, data = dat),\n V = glm(Donations ~ Literacy + Clergy, family = poisson, data = dat)\n)\nIn the rest of this vignette, we will customize tables using tools tinytable and gt. The same process can be used to customize kableExtra, flextable, huxtable, and DT tables.", + "crumbs": [ + "Get started", + "Themes and Styles" + ] + }, + { + "objectID": "vignettes/appearance.html#themes-data-frame", + "href": "vignettes/appearance.html#themes-data-frame", + "title": "Themes and Styles", + "section": "Themes: Data Frame", + "text": "Themes: Data Frame\nA particularly flexible strategy is to apply a theme to the dataframe output format. To illustrate, recall that setting output=\"dataframe\" produces a data frame with a lot of extraneous meta information. To produce a nice table, we have to process that output a bit:\n\nmod <- lm(mpg ~ hp + drat, mtcars)\n\nmodelsummary(mod, output = \"dataframe\")\n\n part term statistic (1)\n1 estimates (Intercept) estimate 10.790\n2 estimates (Intercept) std.error (5.078)\n3 estimates hp estimate -0.052\n4 estimates hp std.error (0.009)\n5 estimates drat estimate 4.698\n6 estimates drat std.error (1.192)\n7 gof Num.Obs. 32\n8 gof R2 0.741\n9 gof R2 Adj. 0.723\n10 gof AIC 169.5\n11 gof BIC 175.4\n12 gof Log.Lik. -80.752\n13 gof F 41.522\n14 gof RMSE 3.02\n\n\nmodelsummary supports the DT table-making package out of the box. But for the sake of illustration, imagine we want to create a table using the DT package with specific customization and options, in a repeatable fashion. To do this, we can create a theming function:\n\nlibrary(DT)\n\ntheme_df <- function(tab) {\n out <- tab\n out$term[out$statistic == \"modelsummary_tmp2\"] <- \" \"\n out$part <- out$statistic <- NULL\n colnames(out)[1] <- \" \"\n datatable(out, rownames = FALSE,\n options = list(pageLength = 30))\n}\n\noptions(\"modelsummary_theme_dataframe\" = theme_df)\nmodelsummary(mod, output = \"dataframe\")\n\n\n\n\n\nRestore default theme:\n\noptions(\"modelsummary_theme_dataframe\" = NULL)", + "crumbs": [ + "Get started", + "Themes and Styles" + ] + }, + { + "objectID": "CITATION.html", + "href": "CITATION.html", + "title": "Citation", + "section": "", + "text": "Citation\nTo cite modelsummary in publications use:\n\n Arel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.”\n _Journal of Statistical Software_, *103*(1), 1-23.\n doi:10.18637/jss.v103.i01 <https://doi.org/10.18637/jss.v103.i01>.\n\nA BibTeX entry for LaTeX users is\n\n @Article{,\n title = {{modelsummary}: Data and Model Summaries in {R}},\n author = {Vincent Arel-Bundock},\n journal = {Journal of Statistical Software},\n year = {2022},\n volume = {103},\n number = {1},\n pages = {1--23},\n doi = {10.18637/jss.v103.i01},\n }", + "crumbs": [ + "Get started", + "Citation" + ] + }, + { + "objectID": "LICENSE.html", + "href": "LICENSE.html", + "title": "License", + "section": "", + "text": "Version 3, 29 June 2007\nCopyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>\nEveryone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\n\n\n\nThe GNU General Public License is a free, copyleft license for software and other kinds of works.\nThe licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program–to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.\nWhen we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.\nTo protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.\nFor example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\nDevelopers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.\nFor the developers’ and authors’ protection, the GPL clearly explains that there is no warranty for this free software. For both users’ and authors’ sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.\nSome devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users’ freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.\nFinally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.\nThe precise terms and conditions for copying, distribution and modification follow.\n\n\n\n\n\n“This License” refers to version 3 of the GNU General Public License.\n“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.\n“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.\nTo “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.\nA “covered work” means either the unmodified Program or a work based on the Program.\nTo “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.\nTo “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.\nAn interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.\n\n\n\nThe “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.\nA “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.\nThe “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.\nThe “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.\nThe Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.\nThe Corresponding Source for a work in source code form is that same work.\n\n\n\nAll rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.\nYou may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.\nConveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.\n\n\n\nNo covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.\nWhen you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work’s users, your or third parties’ legal rights to forbid circumvention of technological measures.\n\n\n\nYou may convey verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.\nYou may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.\n\n\n\nYou may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:\n\na) The work must carry prominent notices stating that you modified it, and giving a relevant date.\nb) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.\nc) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.\nd) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.\n\nA compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation’s users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.\n\n\n\nYou may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:\n\na) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.\nb) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.\nc) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.\nd) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.\ne) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.\nA “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.\n“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.\nIf you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).\nThe requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.\nCorresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.\n\n\n\n“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.\nWhen you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.\nNotwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:\n\na) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or\nb) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or\nc) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or\nd) Limiting the use for publicity purposes of names of licensors or authors of the material; or\ne) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or\nf) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.\n\nAll other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.\nIf you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.\nAdditional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.\n\n\n\nYou may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).\nHowever, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.\nMoreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.\nTermination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.\n\n\n\nYou are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.\n\n\n\nEach time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.\nAn “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party’s predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.\nYou may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.\n\n\n\nA “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor’s “contributor version”.\nA contributor’s “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.\nEach contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor’s essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.\nIn the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.\nIf you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient’s use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.\nIf, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.\nA patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.\nNothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.\n\n\n\nIf conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.\n\n\n\nNotwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.\n\n\n\nThe Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\nEach version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.\nIf the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Program.\nLater license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.\n\n\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n\n\nIf the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.\nEND OF TERMS AND CONDITIONS\n\n\n\n\nIf you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.\nTo do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.\n<one line to give the program's name and a brief idea of what it does.>\nCopyright (C) 2019 Vincent Arel-Bundock\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see <http://www.gnu.org/licenses/>.\nAlso add information on how to contact you by electronic and paper mail.\nIf the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:\nmodelsummary Copyright (C) 2019 Vincent Arel-Bundock\nThis program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.\nThis is free software, and you are welcome to redistribute it\nunder certain conditions; type 'show c' for details.\nThe hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, your program’s commands might be different; for a GUI interface, you would use an “about box”.\nYou should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>.\nThe GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.", + "crumbs": [ + "Get started", + "License" + ] + }, + { + "objectID": "LICENSE.html#gnu-general-public-license", + "href": "LICENSE.html#gnu-general-public-license", + "title": "License", + "section": "", + "text": "Version 3, 29 June 2007\nCopyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>\nEveryone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.", + "crumbs": [ + "Get started", + "License" + ] + }, + { + "objectID": "LICENSE.html#preamble", + "href": "LICENSE.html#preamble", + "title": "License", + "section": "", + "text": "The GNU General Public License is a free, copyleft license for software and other kinds of works.\nThe licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program–to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.\nWhen we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.\nTo protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.\nFor example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\nDevelopers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.\nFor the developers’ and authors’ protection, the GPL clearly explains that there is no warranty for this free software. For both users’ and authors’ sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.\nSome devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users’ freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.\nFinally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.\nThe precise terms and conditions for copying, distribution and modification follow.", + "crumbs": [ + "Get started", + "License" + ] + }, + { + "objectID": "LICENSE.html#terms-and-conditions", + "href": "LICENSE.html#terms-and-conditions", + "title": "License", + "section": "", + "text": "“This License” refers to version 3 of the GNU General Public License.\n“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.\n“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.\nTo “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.\nA “covered work” means either the unmodified Program or a work based on the Program.\nTo “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.\nTo “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.\nAn interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.\n\n\n\nThe “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.\nA “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.\nThe “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.\nThe “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.\nThe Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.\nThe Corresponding Source for a work in source code form is that same work.\n\n\n\nAll rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.\nYou may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.\nConveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.\n\n\n\nNo covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.\nWhen you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work’s users, your or third parties’ legal rights to forbid circumvention of technological measures.\n\n\n\nYou may convey verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.\nYou may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.\n\n\n\nYou may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:\n\na) The work must carry prominent notices stating that you modified it, and giving a relevant date.\nb) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.\nc) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.\nd) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.\n\nA compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation’s users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.\n\n\n\nYou may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:\n\na) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.\nb) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.\nc) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.\nd) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.\ne) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.\nA “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.\n“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.\nIf you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).\nThe requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.\nCorresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.\n\n\n\n“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.\nWhen you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.\nNotwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:\n\na) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or\nb) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or\nc) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or\nd) Limiting the use for publicity purposes of names of licensors or authors of the material; or\ne) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or\nf) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.\n\nAll other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.\nIf you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.\nAdditional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.\n\n\n\nYou may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).\nHowever, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.\nMoreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.\nTermination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.\n\n\n\nYou are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.\n\n\n\nEach time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.\nAn “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party’s predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.\nYou may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.\n\n\n\nA “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor’s “contributor version”.\nA contributor’s “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.\nEach contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor’s essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.\nIn the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.\nIf you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient’s use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.\nIf, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.\nA patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.\nNothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.\n\n\n\nIf conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.\n\n\n\nNotwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.\n\n\n\nThe Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\nEach version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.\nIf the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Program.\nLater license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.\n\n\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n\n\nIf the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.\nEND OF TERMS AND CONDITIONS", + "crumbs": [ + "Get started", + "License" + ] + }, + { + "objectID": "LICENSE.html#how-to-apply-these-terms-to-your-new-programs", + "href": "LICENSE.html#how-to-apply-these-terms-to-your-new-programs", + "title": "License", + "section": "", + "text": "If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.\nTo do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.\n<one line to give the program's name and a brief idea of what it does.>\nCopyright (C) 2019 Vincent Arel-Bundock\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see <http://www.gnu.org/licenses/>.\nAlso add information on how to contact you by electronic and paper mail.\nIf the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:\nmodelsummary Copyright (C) 2019 Vincent Arel-Bundock\nThis program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.\nThis is free software, and you are welcome to redistribute it\nunder certain conditions; type 'show c' for details.\nThe hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, your program’s commands might be different; for a GUI interface, you would use an “about box”.\nYou should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>.\nThe GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.", + "crumbs": [ + "Get started", + "License" + ] + }, + { + "objectID": "man/datasummary_skim.html", + "href": "man/datasummary_skim.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "This function was inspired by the excellent skimr package for R. See the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\n\ndatasummary_skim(\n data,\n output = \"default\",\n type = \"all\",\n fmt = 1,\n title = NULL,\n notes = NULL,\n align = NULL,\n escape = TRUE,\n by = NULL,\n fun_numeric = list(Unique = NUnique, `Missing Pct.` = PercentMissing, Mean = Mean, SD =\n SD, Min = Min, Median = Median, Max = Max, Histogram = function(x) \"\"),\n ...\n)\n\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\ntype\n\n\nString. Variables to summarize: \"all\", \"numeric\", \"categorical\", \"dataset\"\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\nby\n\n\nCharacter vector of grouping variables to compute statistics over.\n\n\n\n\nfun_numeric\n\n\nNamed list of funtions to apply to each column of data. If fun_numeric includes \"Histogram\" or \"Density\", inline plots are inserted.\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\nArel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’\n\n\nlibrary(modelsummary)\n\n\ndat <- mtcars\ndat$vs <- as.logical(dat$vs)\ndat$cyl <- as.factor(dat$cyl)\ndatasummary_skim(dat)\ndatasummary_skim(dat, type = \"categorical\")", + "crumbs": [ + "Get started", + "Functions", + "`datasummary_skim`" + ] + }, + { + "objectID": "man/datasummary_skim.html#quick-overview-of-numeric-or-categorical-variables", + "href": "man/datasummary_skim.html#quick-overview-of-numeric-or-categorical-variables", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "This function was inspired by the excellent skimr package for R. See the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\n\ndatasummary_skim(\n data,\n output = \"default\",\n type = \"all\",\n fmt = 1,\n title = NULL,\n notes = NULL,\n align = NULL,\n escape = TRUE,\n by = NULL,\n fun_numeric = list(Unique = NUnique, `Missing Pct.` = PercentMissing, Mean = Mean, SD =\n SD, Min = Min, Median = Median, Max = Max, Histogram = function(x) \"\"),\n ...\n)\n\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\ntype\n\n\nString. Variables to summarize: \"all\", \"numeric\", \"categorical\", \"dataset\"\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\nby\n\n\nCharacter vector of grouping variables to compute statistics over.\n\n\n\n\nfun_numeric\n\n\nNamed list of funtions to apply to each column of data. If fun_numeric includes \"Histogram\" or \"Density\", inline plots are inserted.\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\nArel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’\n\n\nlibrary(modelsummary)\n\n\ndat <- mtcars\ndat$vs <- as.logical(dat$vs)\ndat$cyl <- as.factor(dat$cyl)\ndatasummary_skim(dat)\ndatasummary_skim(dat, type = \"categorical\")", + "crumbs": [ + "Get started", + "Functions", + "`datasummary_skim`" + ] + }, + { + "objectID": "man/datasummary_df.html", + "href": "man/datasummary_df.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Draw a table from a data.frame\n\n\n\ndatasummary_df(\n data,\n output = \"default\",\n fmt = 2,\n align = NULL,\n hrule = NULL,\n title = NULL,\n notes = NULL,\n add_rows = NULL,\n add_columns = NULL,\n escape = TRUE,\n ...\n)\n\n\n\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nhrule\n\n\nposition of horizontal rules (integer vector)\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\n\n\n\n\nArel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’" + }, + { + "objectID": "man/datasummary_df.html#draw-a-table-from-a-data.frame", + "href": "man/datasummary_df.html#draw-a-table-from-a-data.frame", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Draw a table from a data.frame\n\n\n\ndatasummary_df(\n data,\n output = \"default\",\n fmt = 2,\n align = NULL,\n hrule = NULL,\n title = NULL,\n notes = NULL,\n add_rows = NULL,\n add_columns = NULL,\n escape = TRUE,\n ...\n)\n\n\n\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nhrule\n\n\nposition of horizontal rules (integer vector)\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\n\n\n\n\nArel-Bundock V (2022). “modelsummary: Data and Model Summaries in R.” Journal of Statistical Software, 103(1), 1-23. .’" + }, + { + "objectID": "man/config_modelsummary.html", + "href": "man/config_modelsummary.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Persistent user settings for the modelsummary package\n\n\n\nconfig_modelsummary(\n factory_default,\n factory_latex,\n factory_html,\n factory_markdown,\n startup_message,\n reset = FALSE\n)\n\n\n\n\n\n\n\nfactory_default\n\n\nDefault output format: \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\n\n\nfactory_latex\n\n\nName of package used to generate LaTeX output when output=“latex”.\n\n\n\n\nfactory_html\n\n\nName of package used to generate LaTeX output when output=“html”.\n\n\n\n\nfactory_markdown\n\n\nName of package used to generate LaTeX output when output=“markdown”.\n\n\n\n\nstartup_message\n\n\nTRUE or FALSE to show warnings at startup\n\n\n\n\nreset\n\n\nTRUE to return to default settings.", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`config_modelsummary`" + ] + }, + { + "objectID": "man/config_modelsummary.html#persistent-user-settings-for-the-modelsummary-package", + "href": "man/config_modelsummary.html#persistent-user-settings-for-the-modelsummary-package", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Persistent user settings for the modelsummary package\n\n\n\nconfig_modelsummary(\n factory_default,\n factory_latex,\n factory_html,\n factory_markdown,\n startup_message,\n reset = FALSE\n)\n\n\n\n\n\n\n\nfactory_default\n\n\nDefault output format: \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\n\n\nfactory_latex\n\n\nName of package used to generate LaTeX output when output=“latex”.\n\n\n\n\nfactory_html\n\n\nName of package used to generate LaTeX output when output=“html”.\n\n\n\n\nfactory_markdown\n\n\nName of package used to generate LaTeX output when output=“markdown”.\n\n\n\n\nstartup_message\n\n\nTRUE or FALSE to show warnings at startup\n\n\n\n\nreset\n\n\nTRUE to return to default settings.", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`config_modelsummary`" + ] + }, + { + "objectID": "man/datasummary_crosstab.html", + "href": "man/datasummary_crosstab.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Convenience function to tabulate counts, cell percentages, and row/column percentages for categorical variables. See the Details section for a description of the internal design. For more complex cross tabulations, use datasummary directly. See the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\n\ndatasummary_crosstab(\n formula,\n statistic = 1 ~ 1 + N + Percent(\"row\"),\n data,\n output = \"default\",\n fmt = 1,\n title = NULL,\n notes = NULL,\n align = NULL,\n add_columns = NULL,\n add_rows = NULL,\n sparse_header = TRUE,\n escape = TRUE,\n ...\n)\n\n\n\n\n\nformula\n\n\nA two-sided formula to describe the table: rows ~ columns, where rows and columns are variables in the data. Rows and columns may contain interactions, e.g., var1 * var2 ~ var3.\n\n\n\n\nstatistic\n\n\nA formula of the form 1 ~ 1 + N + Percent(“row”). The left-hand side may only be empty or contain a 1 to include row totals. The right-hand side may contain: 1 for column totals, N for counts, Percent() for cell percentages, Percent(“row”) for row percentages, Percent(“col”) for column percentages.\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nsparse_header\n\n\nTRUE or FALSE. TRUE eliminates column headers which have a unique label across all columns, except for the row immediately above the data. FALSE keeps all headers. The order in which terms are entered in the formula determines the order in which headers appear. For example, x~mean*z will print the mean-related header above the z-related header.’\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\n\ndatasummary_crosstab is a wrapper around the datasummary function. This wrapper works by creating a customized formula and by feeding it to datasummary. The customized formula comes in two parts.\nFirst, we take a two-sided formula supplied by the formula argument. All variables of that formula are wrapped in a Factor() call to ensure that the variables are treated as categorical.\nSecond, the statistic argument gives a two-sided formula which specifies the statistics to include in the table. datasummary_crosstab modifies this formula automatically to include \"clean\" labels.\nFinally, the formula and statistic formulas are combined into a single formula which is fed directly to the datasummary function to produce the table.\nVariables in formula are automatically wrapped in Factor().\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\n# crosstab of two variables, showing counts, row percentages, and row/column totals\ndatasummary_crosstab(cyl ~ gear, data = mtcars)\n\n \n\n \n \n\ntinytable_53soqsg0zyxpdd7d792m\n\n\n \n\ncyl\n \n 3\n 4\n 5\n All\n \n\n\n4 \n N \n 1 \n 8 \n 2 \n 11 \n \n\n \n % row\n 9.1 \n 72.7\n 18.2\n 100.0\n \n\n6 \n N \n 2 \n 4 \n 1 \n 7 \n \n\n \n % row\n 28.6\n 57.1\n 14.3\n 100.0\n \n\n8 \n N \n 12 \n 0 \n 2 \n 14 \n \n\n \n % row\n 85.7\n 0.0 \n 14.3\n 100.0\n \n\nAll\n N \n 15 \n 12 \n 5 \n 32 \n \n\n \n % row\n 46.9\n 37.5\n 15.6\n 100.0\n \n\n\n\n\n \n\n# crosstab of two variables, showing counts only and no totals\ndatasummary_crosstab(cyl ~ gear, statistic = ~ N, data = mtcars)\n\n \n\n \n \n\ntinytable_woqc6c15y86ppbroec7i\n\n\n \n\ncyl\n \n 3\n 4\n 5\n \n\n\n4\n N\n 1 \n 8\n 2\n \n\n6\n N\n 2 \n 4\n 1\n \n\n8\n N\n 12\n 0\n 2\n \n\n\n\n\n \n\n# crosstab of three variables\n datasummary_crosstab(am * cyl ~ gear, data = mtcars)\n\n \n\n \n \n\ntinytable_nueq2d2yzkxgab84fm9s\n\n\n \n\nam\n cyl\n \n 3\n 4\n 5\n All\n \n\n\n0\n 4 \n N \n 1 \n 2 \n 0 \n 3 \n \n\n \n \n % row\n 33.3 \n 66.7\n 0.0 \n 100.0\n \n\n \n 6 \n N \n 2 \n 2 \n 0 \n 4 \n \n\n \n \n % row\n 50.0 \n 50.0\n 0.0 \n 100.0\n \n\n \n 8 \n N \n 12 \n 0 \n 0 \n 12 \n \n\n \n \n % row\n 100.0\n 0.0 \n 0.0 \n 100.0\n \n\n1\n 4 \n N \n 0 \n 6 \n 2 \n 8 \n \n\n \n \n % row\n 0.0 \n 75.0\n 25.0 \n 100.0\n \n\n \n 6 \n N \n 0 \n 2 \n 1 \n 3 \n \n\n \n \n % row\n 0.0 \n 66.7\n 33.3 \n 100.0\n \n\n \n 8 \n N \n 0 \n 0 \n 2 \n 2 \n \n\n \n \n % row\n 0.0 \n 0.0 \n 100.0\n 100.0\n \n\n \n All\n N \n 15 \n 12 \n 5 \n 32 \n \n\n \n \n % row\n 46.9 \n 37.5\n 15.6 \n 100.0\n \n\n\n\n\n \n\n# crosstab with two variables and column percentages \ndatasummary_crosstab(am ~ gear, statistic = ~ Percent(\"col\"), data = mtcars)\n\n \n\n \n \n\ntinytable_v0t9xr1poxhq1onhr8cf\n\n\n \n\nam\n \n 3\n 4\n 5\n \n\n\n0\n % col\n 100.0\n 33.3\n 0.0 \n \n\n1\n % col\n 0.0 \n 66.7\n 100.0", + "crumbs": [ + "Get started", + "Functions", + "`datasummary_crosstab`" + ] + }, + { + "objectID": "man/datasummary_crosstab.html#cross-tabulations-for-categorical-variables", + "href": "man/datasummary_crosstab.html#cross-tabulations-for-categorical-variables", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Convenience function to tabulate counts, cell percentages, and row/column percentages for categorical variables. See the Details section for a description of the internal design. For more complex cross tabulations, use datasummary directly. See the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\n\ndatasummary_crosstab(\n formula,\n statistic = 1 ~ 1 + N + Percent(\"row\"),\n data,\n output = \"default\",\n fmt = 1,\n title = NULL,\n notes = NULL,\n align = NULL,\n add_columns = NULL,\n add_rows = NULL,\n sparse_header = TRUE,\n escape = TRUE,\n ...\n)\n\n\n\n\n\nformula\n\n\nA two-sided formula to describe the table: rows ~ columns, where rows and columns are variables in the data. Rows and columns may contain interactions, e.g., var1 * var2 ~ var3.\n\n\n\n\nstatistic\n\n\nA formula of the form 1 ~ 1 + N + Percent(“row”). The left-hand side may only be empty or contain a 1 to include row totals. The right-hand side may contain: 1 for column totals, N for counts, Percent() for cell percentages, Percent(“row”) for row percentages, Percent(“col”) for column percentages.\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nsparse_header\n\n\nTRUE or FALSE. TRUE eliminates column headers which have a unique label across all columns, except for the row immediately above the data. FALSE keeps all headers. The order in which terms are entered in the formula determines the order in which headers appear. For example, x~mean*z will print the mean-related header above the z-related header.’\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\n\ndatasummary_crosstab is a wrapper around the datasummary function. This wrapper works by creating a customized formula and by feeding it to datasummary. The customized formula comes in two parts.\nFirst, we take a two-sided formula supplied by the formula argument. All variables of that formula are wrapped in a Factor() call to ensure that the variables are treated as categorical.\nSecond, the statistic argument gives a two-sided formula which specifies the statistics to include in the table. datasummary_crosstab modifies this formula automatically to include \"clean\" labels.\nFinally, the formula and statistic formulas are combined into a single formula which is fed directly to the datasummary function to produce the table.\nVariables in formula are automatically wrapped in Factor().\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\n# crosstab of two variables, showing counts, row percentages, and row/column totals\ndatasummary_crosstab(cyl ~ gear, data = mtcars)\n\n \n\n \n \n\ntinytable_53soqsg0zyxpdd7d792m\n\n\n \n\ncyl\n \n 3\n 4\n 5\n All\n \n\n\n4 \n N \n 1 \n 8 \n 2 \n 11 \n \n\n \n % row\n 9.1 \n 72.7\n 18.2\n 100.0\n \n\n6 \n N \n 2 \n 4 \n 1 \n 7 \n \n\n \n % row\n 28.6\n 57.1\n 14.3\n 100.0\n \n\n8 \n N \n 12 \n 0 \n 2 \n 14 \n \n\n \n % row\n 85.7\n 0.0 \n 14.3\n 100.0\n \n\nAll\n N \n 15 \n 12 \n 5 \n 32 \n \n\n \n % row\n 46.9\n 37.5\n 15.6\n 100.0\n \n\n\n\n\n \n\n# crosstab of two variables, showing counts only and no totals\ndatasummary_crosstab(cyl ~ gear, statistic = ~ N, data = mtcars)\n\n \n\n \n \n\ntinytable_woqc6c15y86ppbroec7i\n\n\n \n\ncyl\n \n 3\n 4\n 5\n \n\n\n4\n N\n 1 \n 8\n 2\n \n\n6\n N\n 2 \n 4\n 1\n \n\n8\n N\n 12\n 0\n 2\n \n\n\n\n\n \n\n# crosstab of three variables\n datasummary_crosstab(am * cyl ~ gear, data = mtcars)\n\n \n\n \n \n\ntinytable_nueq2d2yzkxgab84fm9s\n\n\n \n\nam\n cyl\n \n 3\n 4\n 5\n All\n \n\n\n0\n 4 \n N \n 1 \n 2 \n 0 \n 3 \n \n\n \n \n % row\n 33.3 \n 66.7\n 0.0 \n 100.0\n \n\n \n 6 \n N \n 2 \n 2 \n 0 \n 4 \n \n\n \n \n % row\n 50.0 \n 50.0\n 0.0 \n 100.0\n \n\n \n 8 \n N \n 12 \n 0 \n 0 \n 12 \n \n\n \n \n % row\n 100.0\n 0.0 \n 0.0 \n 100.0\n \n\n1\n 4 \n N \n 0 \n 6 \n 2 \n 8 \n \n\n \n \n % row\n 0.0 \n 75.0\n 25.0 \n 100.0\n \n\n \n 6 \n N \n 0 \n 2 \n 1 \n 3 \n \n\n \n \n % row\n 0.0 \n 66.7\n 33.3 \n 100.0\n \n\n \n 8 \n N \n 0 \n 0 \n 2 \n 2 \n \n\n \n \n % row\n 0.0 \n 0.0 \n 100.0\n 100.0\n \n\n \n All\n N \n 15 \n 12 \n 5 \n 32 \n \n\n \n \n % row\n 46.9 \n 37.5\n 15.6 \n 100.0\n \n\n\n\n\n \n\n# crosstab with two variables and column percentages \ndatasummary_crosstab(am ~ gear, statistic = ~ Percent(\"col\"), data = mtcars)\n\n \n\n \n \n\ntinytable_v0t9xr1poxhq1onhr8cf\n\n\n \n\nam\n \n 3\n 4\n 5\n \n\n\n0\n % col\n 100.0\n 33.3\n 0.0 \n \n\n1\n % col\n 0.0 \n 66.7\n 100.0", + "crumbs": [ + "Get started", + "Functions", + "`datasummary_crosstab`" + ] + }, + { + "objectID": "man/dvnames.html", + "href": "man/dvnames.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A convenience function for use with a regression model or list of regression models. Returns a named list of models, where the names are the models’ respective dependent variables. Pass your list of models to dvnames before sending to modelsummary to automatically get dependent variable-titled columns.\n\ndvnames(models, number = FALSE, strip = FALSE, fill = \"Model\")\n\n\n\n\n\nmodels\n\n\nA regression model or list of regression models\n\n\n\n\nnumber\n\n\nShould the models be numbered (1), (2), etc., in addition to their dependent variable names?\n\n\n\n\nstrip\n\n\nboolean FALSE returns the dependent variable names as they appear in the model. TRUE returns the dependent variable names as they appear in the data, without transformations.\n\n\n\n\nfill\n\n\nIf insight::find_response() cannot find a response, the column title to use in its place. Set to ’ ’ to leave blank.\n\n\n\n\nlibrary(modelsummary)\n\n\nm1 <- lm(mpg ~ hp, data = mtcars)\nm2 <- lm(mpg ~ hp + wt, data = mtcars)\n\n# Without dvnames, column names are (1) and (2)\nmodelsummary(list(m1, m2))\n\n \n\n \n \n\ntinytable_ur5sjdxkkai5miru692t\n\n\n \n\n \n (1)\n (2)\n \n\n\n(Intercept)\n 30.099 \n 37.227 \n \n\n \n (1.634)\n (1.599)\n \n\nhp \n -0.068 \n -0.032 \n \n\n \n (0.010)\n (0.009)\n \n\nwt \n \n -3.878 \n \n\n \n \n (0.633)\n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 \n 0.602 \n 0.827 \n \n\nR2 Adj. \n 0.589 \n 0.815 \n \n\nAIC \n 181.2 \n 156.7 \n \n\nBIC \n 185.6 \n 162.5 \n \n\nLog.Lik. \n -87.619\n -74.326\n \n\nF \n 45.460 \n 69.211 \n \n\nRMSE \n 3.74 \n 2.47 \n \n\n\n\n\n \n\n# With dvnames, they are \"mpg\" and \"mpg\"\nmodelsummary(dvnames(list(m1,m2)))\n\n \n\n \n \n\ntinytable_koq29n1et1odeaehv0mo\n\n\n \n\n \n mpg\n mpg \n \n\n\n(Intercept)\n 30.099 \n 37.227 \n \n\n \n (1.634)\n (1.599)\n \n\nhp \n -0.068 \n -0.032 \n \n\n \n (0.010)\n (0.009)\n \n\nwt \n \n -3.878 \n \n\n \n \n (0.633)\n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 \n 0.602 \n 0.827 \n \n\nR2 Adj. \n 0.589 \n 0.815 \n \n\nAIC \n 181.2 \n 156.7 \n \n\nBIC \n 185.6 \n 162.5 \n \n\nLog.Lik. \n -87.619\n -74.326\n \n\nF \n 45.460 \n 69.211 \n \n\nRMSE \n 3.74 \n 2.47", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`dvnames`" + ] + }, + { + "objectID": "man/dvnames.html#title-models-with-their-dependent-variables", + "href": "man/dvnames.html#title-models-with-their-dependent-variables", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A convenience function for use with a regression model or list of regression models. Returns a named list of models, where the names are the models’ respective dependent variables. Pass your list of models to dvnames before sending to modelsummary to automatically get dependent variable-titled columns.\n\ndvnames(models, number = FALSE, strip = FALSE, fill = \"Model\")\n\n\n\n\n\nmodels\n\n\nA regression model or list of regression models\n\n\n\n\nnumber\n\n\nShould the models be numbered (1), (2), etc., in addition to their dependent variable names?\n\n\n\n\nstrip\n\n\nboolean FALSE returns the dependent variable names as they appear in the model. TRUE returns the dependent variable names as they appear in the data, without transformations.\n\n\n\n\nfill\n\n\nIf insight::find_response() cannot find a response, the column title to use in its place. Set to ’ ’ to leave blank.\n\n\n\n\nlibrary(modelsummary)\n\n\nm1 <- lm(mpg ~ hp, data = mtcars)\nm2 <- lm(mpg ~ hp + wt, data = mtcars)\n\n# Without dvnames, column names are (1) and (2)\nmodelsummary(list(m1, m2))\n\n \n\n \n \n\ntinytable_ur5sjdxkkai5miru692t\n\n\n \n\n \n (1)\n (2)\n \n\n\n(Intercept)\n 30.099 \n 37.227 \n \n\n \n (1.634)\n (1.599)\n \n\nhp \n -0.068 \n -0.032 \n \n\n \n (0.010)\n (0.009)\n \n\nwt \n \n -3.878 \n \n\n \n \n (0.633)\n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 \n 0.602 \n 0.827 \n \n\nR2 Adj. \n 0.589 \n 0.815 \n \n\nAIC \n 181.2 \n 156.7 \n \n\nBIC \n 185.6 \n 162.5 \n \n\nLog.Lik. \n -87.619\n -74.326\n \n\nF \n 45.460 \n 69.211 \n \n\nRMSE \n 3.74 \n 2.47 \n \n\n\n\n\n \n\n# With dvnames, they are \"mpg\" and \"mpg\"\nmodelsummary(dvnames(list(m1,m2)))\n\n \n\n \n \n\ntinytable_koq29n1et1odeaehv0mo\n\n\n \n\n \n mpg\n mpg \n \n\n\n(Intercept)\n 30.099 \n 37.227 \n \n\n \n (1.634)\n (1.599)\n \n\nhp \n -0.068 \n -0.032 \n \n\n \n (0.010)\n (0.009)\n \n\nwt \n \n -3.878 \n \n\n \n \n (0.633)\n \n\nNum.Obs. \n 32 \n 32 \n \n\nR2 \n 0.602 \n 0.827 \n \n\nR2 Adj. \n 0.589 \n 0.815 \n \n\nAIC \n 181.2 \n 156.7 \n \n\nBIC \n 185.6 \n 162.5 \n \n\nLog.Lik. \n -87.619\n -74.326\n \n\nF \n 45.460 \n 69.211 \n \n\nRMSE \n 3.74 \n 2.47", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`dvnames`" + ] + }, + { + "objectID": "man/fmt_sprintf.html", + "href": "man/fmt_sprintf.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with the sprintf() function in the fmt argument\n\n\n\nfmt_sprintf(fmt)\n\n\n\n\n\n\n\nfmt\n\n\nA string to control sprintf(), such as “%.3f” to keep 3 decimal digits. See ?sprintf", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_sprintf`" + ] + }, + { + "objectID": "man/fmt_sprintf.html#rounding-with-the-sprintf-function-in-the-fmt-argument", + "href": "man/fmt_sprintf.html#rounding-with-the-sprintf-function-in-the-fmt-argument", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Rounding with the sprintf() function in the fmt argument\n\n\n\nfmt_sprintf(fmt)\n\n\n\n\n\n\n\nfmt\n\n\nA string to control sprintf(), such as “%.3f” to keep 3 decimal digits. See ?sprintf", + "crumbs": [ + "Get started", + "Functions", + "Formatting", + "`fmt_sprintf`" + ] + }, + { + "objectID": "man/datasummary.html", + "href": "man/datasummary.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Summary tables using 2-sided formulae: crosstabs, frequencies, table 1s and more.\nDescription\ndatasummary can use any summary function which produces one numeric or character value per variable. The examples section of this documentation shows how to define custom summary functions.\nmodelsummary also supplies several shortcut summary functions which can be used in datasummary() formulas: Min, Max, Mean, Median, Var, SD, NPercent, NUnique, Ncol, P0, P25, P50, P75, P100.\nSee the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\nUsage\ndatasummary(\n formula,\n data,\n output = \"default\",\n fmt = 2,\n title = NULL,\n notes = NULL,\n align = NULL,\n add_columns = NULL,\n add_rows = NULL,\n sparse_header = TRUE,\n escape = TRUE,\n ...\n)\n\nArguments\n\n\n\nformula\n\n\nA two-sided formula to describe the table: rows ~ columns. See the Examples section for a mini-tutorial and the Details section for more resources. Grouping/nesting variables can appear on both sides of the formula, but all summary functions must be on one side.\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nsparse_header\n\n\nTRUE or FALSE. TRUE eliminates column headers which have a unique label across all columns, except for the row immediately above the data. FALSE keeps all headers. The order in which terms are entered in the formula determines the order in which headers appear. For example, x~mean*z will print the mean-related header above the z-related header.’\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\nDetails\nVisit the ‘modelsummary’ website for more usage examples: https://modelsummary.com\nThe ‘datasummary’ function is a thin wrapper around the ‘tabular’ function from the ‘tables’ package. More details about table-making formulas can be found in the ‘tables’ package documentation: ?tables::tabular\nHierarchical or \"nested\" column labels are only available for these output formats: tinytable, kableExtra, gt, html, rtf, and LaTeX. When saving tables to other formats, nested labels will be combined to a \"flat\" header.\nGlobal Options\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nModel labels: default column names\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nTable-making packages\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nTable themes\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nModel extraction functions\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nFormatting numeric entries\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nLaTeX preamble\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\nExamples\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\n# The left-hand side of the formula describes rows, and the right-hand side\n# describes columns. This table uses the \"mpg\" variable as a row and the \"mean\"\n# function as a column:\n\ndatasummary(mpg ~ mean, data = mtcars)\n\n \n\n \n \n\ntinytable_oengsxmsr0dg0fewop2v\n\n\n \n\n \n mean\n \n\nmpg\n 20.09\n \n\n\n\n \n\n# This table uses the \"mean\" function as a row and the \"mpg\" variable as a column:\n\ndatasummary(mean ~ mpg, data = mtcars)\n\n \n\n \n \n\ntinytable_qiah97bez6yp3tb1yjz8\n\n\n \n\n \n mpg\n \n\nmean\n 20.09\n \n\n\n\n \n\n# Display several variables or functions of the data using the \"+\"\n# concatenation operator. This table has 2 rows and 2 columns:\n\ndatasummary(hp + mpg ~ mean + sd, data = mtcars)\n\n \n\n \n \n\ntinytable_0rwqzbz7y1fs1jwtt2f3\n\n\n \n\n \n mean\n sd\n \n\n\nhp \n 146.69\n 68.56\n \n\nmpg\n 20.09 \n 6.03 \n \n\n\n\n\n \n\n# Nest variables or statistics inside a \"factor\" variable using the \"*\" nesting\n# operator. This table shows the mean of \"hp\" and \"mpg\" for each value of\n# \"cyl\":\n\nmtcars$cyl <- as.factor(mtcars$cyl)\ndatasummary(hp + mpg ~ cyl * mean, data = mtcars)\n\n \n\n \n \n\ntinytable_9n5p3qmb9xrfcjfwzs4t\n\n\n \n\n \n 4\n 6\n 8\n \n\n\nhp \n 82.64\n 122.29\n 209.21\n \n\nmpg\n 26.66\n 19.74 \n 15.10 \n \n\n\n\n\n \n\n# If you don't want to convert your original data\n# to factors, you can use the 'Factor()'\n# function inside 'datasummary' to obtain an identical result:\n\ndatasummary(hp + mpg ~ Factor(cyl) * mean, data = mtcars)\n\n \n\n \n \n\ntinytable_a48qfecth0mdjgg881bq\n\n\n \n\n \n 4\n 6\n 8\n \n\n\nhp \n 82.64\n 122.29\n 209.21\n \n\nmpg\n 26.66\n 19.74 \n 15.10 \n \n\n\n\n\n \n\n# You can nest several variables or statistics inside a factor by using\n# parentheses. This table shows the mean and the standard deviation for each\n# subset of \"cyl\":\n\ndatasummary(hp + mpg ~ cyl * (mean + sd), data = mtcars)\n\n \n\n \n \n\ntinytable_gqhdjyyk9ganywtrpbtp\n\n\n \n\n\n \n4\n6\n8\n\n\n \n mean\n sd\n mean\n sd\n mean\n sd\n \n\n\n\nhp \n 82.64\n 20.93\n 122.29\n 24.26\n 209.21\n 50.98\n \n\nmpg\n 26.66\n 4.51 \n 19.74 \n 1.45 \n 15.10 \n 2.56 \n \n\n\n\n\n \n\n# Summarize all numeric variables with 'All()'\ndatasummary(All(mtcars) ~ mean + sd, data = mtcars)\n\n \n\n \n \n\ntinytable_yjilnuk7uhhyqu79aocv\n\n\n \n\n \n mean\n sd\n \n\n\nmpg \n 20.09 \n 6.03 \n \n\ndisp\n 230.72\n 123.94\n \n\nhp \n 146.69\n 68.56 \n \n\ndrat\n 3.60 \n 0.53 \n \n\nwt \n 3.22 \n 0.98 \n \n\nqsec\n 17.85 \n 1.79 \n \n\nvs \n 0.44 \n 0.50 \n \n\nam \n 0.41 \n 0.50 \n \n\ngear\n 3.69 \n 0.74 \n \n\ncarb\n 2.81 \n 1.62 \n \n\n\n\n\n \n\n# Define custom summary statistics. Your custom function should accept a vector\n# of numeric values and return a single numeric or string value:\n\nminmax <- function(x) sprintf(\"[%.2f, %.2f]\", min(x), max(x))\nmean_na <- function(x) mean(x, na.rm = TRUE)\n\ndatasummary(hp + mpg ~ minmax + mean_na, data = mtcars)\n\n \n\n \n \n\ntinytable_dqe39s3tigd92mr9n0si\n\n\n \n\n \n minmax\n mean_na\n \n\n\nhp \n [52.00, 335.00]\n 146.69\n \n\nmpg\n [10.40, 33.90] \n 20.09 \n \n\n\n\n\n \n\n# To handle missing values, you can pass arguments to your functions using\n# '*Arguments()'\n\ndatasummary(hp + mpg ~ mean * Arguments(na.rm = TRUE), data = mtcars)\n\n \n\n \n \n\ntinytable_3ewcp3pjk8wpjut9smtg\n\n\n \n\n \n mean\n \n\n\nhp \n 146.69\n \n\nmpg\n 20.09 \n \n\n\n\n\n \n\n# For convenience, 'modelsummary' supplies several convenience functions\n# with the argument `na.rm=TRUE` by default: Mean, Median, Min, Max, SD, Var,\n# P0, P25, P50, P75, P100, NUnique, Histogram\n\n#datasummary(hp + mpg ~ Mean + SD + Histogram, data = mtcars)\n\n# These functions also accept a 'fmt' argument which allows you to\n# round/format the results\n\ndatasummary(hp + mpg ~ Mean * Arguments(fmt = \"%.3f\") + SD * Arguments(fmt = \"%.1f\"), data = mtcars)\n\n \n\n \n \n\ntinytable_9ezlm1ah64gh1d4i6oco\n\n\n \n\n \n Mean\n SD\n \n\n\nhp \n 146.688\n 68.6\n \n\nmpg\n 20.091 \n 6.0 \n \n\n\n\n\n \n\n# Save your tables to a variety of output formats:\nf <- hp + mpg ~ Mean + SD\n#datasummary(f, data = mtcars, output = 'table.html')\n#datasummary(f, data = mtcars, output = 'table.tex')\n#datasummary(f, data = mtcars, output = 'table.md')\n#datasummary(f, data = mtcars, output = 'table.docx')\n#datasummary(f, data = mtcars, output = 'table.pptx')\n#datasummary(f, data = mtcars, output = 'table.jpg')\n#datasummary(f, data = mtcars, output = 'table.png')\n\n# Display human-readable code\n#datasummary(f, data = mtcars, output = 'html')\n#datasummary(f, data = mtcars, output = 'markdown')\n#datasummary(f, data = mtcars, output = 'latex')\n\n# Return a table object to customize using a table-making package\n#datasummary(f, data = mtcars, output = 'tinytable')\n#datasummary(f, data = mtcars, output = 'gt')\n#datasummary(f, data = mtcars, output = 'kableExtra')\n#datasummary(f, data = mtcars, output = 'flextable')\n#datasummary(f, data = mtcars, output = 'huxtable')\n\n# add_rows\nnew_rows <- data.frame(a = 1:2, b = 2:3, c = 4:5)\nattr(new_rows, 'position') <- c(1, 3)\ndatasummary(mpg + hp ~ mean + sd, data = mtcars, add_rows = new_rows)\n\n \n\n \n \n\ntinytable_zpjqcle29gs9e5zczhfn\n\n\n \n\n \n mean\n sd\n \n\n\n1.00\n 2.00 \n 4.00 \n \n\nmpg \n 20.09 \n 6.03 \n \n\n2.00\n 3.00 \n 5.00 \n \n\nhp \n 146.69\n 68.56", + "crumbs": [ + "Get started", + "Functions", + "`datasummary`" + ] + }, + { + "objectID": "man/get_gof.html", + "href": "man/get_gof.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A unified approach to extract results from a wide variety of models. For some models get_gof attaches useful attributes to the output. You can access this information by calling the attributes function: attributes(get_estimates(model))\n\n\n\nget_gof(model, gof_function = NULL, vcov_type = NULL, ...)\n\n\n\n\n\n\n\nmodel\n\n\na single model object\n\n\n\n\ngof_function\n\n\nfunction which accepts a model object in the model argument and returns a 1-row data.frame with one custom goodness-of-fit statistic per column.\n\n\n\n\nvcov_type\n\n\nstring vcov type to add at the bottom of the table\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`get_gof`" + ] + }, + { + "objectID": "man/get_gof.html#extract-goodness-of-fit-statistics-a-tidy-format.", + "href": "man/get_gof.html#extract-goodness-of-fit-statistics-a-tidy-format.", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A unified approach to extract results from a wide variety of models. For some models get_gof attaches useful attributes to the output. You can access this information by calling the attributes function: attributes(get_estimates(model))\n\n\n\nget_gof(model, gof_function = NULL, vcov_type = NULL, ...)\n\n\n\n\n\n\n\nmodel\n\n\na single model object\n\n\n\n\ngof_function\n\n\nfunction which accepts a model object in the model argument and returns a 1-row data.frame with one custom goodness-of-fit statistic per column.\n\n\n\n\nvcov_type\n\n\nstring vcov type to add at the bottom of the table\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`get_gof`" + ] + }, + { + "objectID": "man/datasummary_correlation.html", + "href": "man/datasummary_correlation.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "The names of the variables displayed in the correlation table are the names of the columns in the data. You can rename those columns (with or without spaces) to produce a table of human-readable variables. See the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\n\ndatasummary_correlation(\n data,\n output = \"default\",\n method = \"pearson\",\n fmt = 2,\n align = NULL,\n add_rows = NULL,\n add_columns = NULL,\n title = NULL,\n notes = NULL,\n escape = TRUE,\n ...\n)\n\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nmethod\n\n\ncharacter or function\n\n\ncharacter: \"pearson\", \"kendall\", \"spearman\", or \"pearspear\" (Pearson correlations above and Spearman correlations below the diagonal)\n\n\nfunction: takes a data.frame with numeric columns and returns a square matrix or data.frame with unique row.names and colnames corresponding to variable names. Note that the datasummary_correlation_format can often be useful for formatting the output of custom correlation functions.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nother parameters are passed through to the table-making packages.\n\n\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\n# clean variable names (base R)\ndat <- mtcars[, c(\"mpg\", \"hp\")]\ncolnames(dat) <- c(\"Miles / Gallon\", \"Horse Power\")\ndatasummary_correlation(dat)\n\n \n\n \n \n\ntinytable_lqm5yep0ilher18ulbvk\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1 \n .\n \n\nHorse Power \n -.78\n 1\n \n\n\n\n\n \n\n# clean variable names (tidyverse)\nlibrary(tidyverse)\ndat <- mtcars %>%\n select(`Miles / Gallon` = mpg,\n `Horse Power` = hp)\ndatasummary_correlation(dat)\n\n \n\n \n \n\ntinytable_3kclndgxea7xtjuujcpi\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1 \n .\n \n\nHorse Power \n -.78\n 1\n \n\n\n\n\n \n\n# alternative methods\ndatasummary_correlation(dat, method = \"pearspear\")\n\n \n\n \n \n\ntinytable_dz0p5x5la5zv0nyf1slh\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1 \n -.78\n \n\nHorse Power \n -.89\n 1 \n \n\n\n\n\n \n\n# custom function\ncor_fun <- function(x) cor(x, method = \"kendall\")\ndatasummary_correlation(dat, method = cor_fun)\n\n \n\n \n \n\ntinytable_smtzy6r4mpzoxb0ao498\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1.00\n -.74\n \n\nHorse Power \n -.74\n 1.00\n \n\n\n\n\n \n\n# rename columns alphabetically and include a footnote for reference\nnote <- sprintf(\"(%s) %s\", letters[1:ncol(dat)], colnames(dat))\nnote <- paste(note, collapse = \"; \")\n\ncolnames(dat) <- sprintf(\"(%s)\", letters[1:ncol(dat)])\n\ndatasummary_correlation(dat, notes = note)\n\n \n\n \n \n\ntinytable_j2w1c0tbx9jr58f7almw\n\n\n \n\n \n (a)\n (b)\n \n(a) Miles / Gallon; (b) Horse Power\n\n\n(a)\n 1 \n .\n \n\n(b)\n -.78\n 1\n \n\n\n\n\n \n\n# `datasummary_correlation_format`: custom function with formatting\ndat <- mtcars[, c(\"mpg\", \"hp\", \"disp\")]\n\ncor_fun <- function(x) {\n out <- cor(x, method = \"kendall\")\n datasummary_correlation_format(\n out,\n fmt = 2,\n upper_triangle = \"x\",\n diagonal = \".\")\n}\n\ndatasummary_correlation(dat, method = cor_fun)\n\n \n\n \n \n\ntinytable_qm5ndlgshzupo12elph5\n\n\n \n\n \n mpg\n hp\n disp\n \n\n\nmpg \n . \n x \n x\n \n\nhp \n -.74\n . \n x\n \n\ndisp\n -.77\n .67\n .\n \n\n\n\n\n \n\n# use kableExtra and psych to color significant cells\nlibrary(psych)\nlibrary(kableExtra)\n\ndat <- mtcars[, c(\"vs\", \"hp\", \"gear\")]\n\ncor_fun <- function(dat) {\n # compute correlations and format them\n correlations <- data.frame(cor(dat))\n correlations <- datasummary_correlation_format(correlations, fmt = 2)\n\n # calculate pvalues using the `psych` package\n pvalues <- psych::corr.test(dat)$p\n\n # use `kableExtra::cell_spec` to color significant cells\n for (i in 1:nrow(correlations)) {\n for (j in 1:ncol(correlations)) {\n if (pvalues[i, j] < 0.05 && i != j) {\n correlations[i, j] <- cell_spec(correlations[i, j], background = \"pink\")\n }\n }\n }\n return(correlations)\n}\n\n# The `escape=FALSE` is important here!\ndatasummary_correlation(dat, method = cor_fun, escape = FALSE)\n\n \n\n \n \n\ntinytable_72vj0rbb0ntxzq78x1ey\n\n\n \n\n \n vs\n hp\n gear\n \n\n\nvs \n 1.00 \n -.72\n .21 \n \n\nhp \n -.72\n 1.00 \n -.13\n \n\ngear\n .21 \n -.13 \n 1.00", + "crumbs": [ + "Get started", + "Functions", + "`datasummary_correlation`" + ] + }, + { + "objectID": "man/datasummary_correlation.html#generate-a-correlation-table-for-all-numeric-variables-in-your-dataset.", + "href": "man/datasummary_correlation.html#generate-a-correlation-table-for-all-numeric-variables-in-your-dataset.", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "The names of the variables displayed in the correlation table are the names of the columns in the data. You can rename those columns (with or without spaces) to produce a table of human-readable variables. See the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\n\ndatasummary_correlation(\n data,\n output = \"default\",\n method = \"pearson\",\n fmt = 2,\n align = NULL,\n add_rows = NULL,\n add_columns = NULL,\n title = NULL,\n notes = NULL,\n escape = TRUE,\n ...\n)\n\n\n\n\n\ndata\n\n\nA data.frame (or tibble)\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nmethod\n\n\ncharacter or function\n\n\ncharacter: \"pearson\", \"kendall\", \"spearman\", or \"pearspear\" (Pearson correlations above and Spearman correlations below the diagonal)\n\n\nfunction: takes a data.frame with numeric columns and returns a square matrix or data.frame with unique row.names and colnames corresponding to variable names. Note that the datasummary_correlation_format can often be useful for formatting the output of custom correlation functions.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nother parameters are passed through to the table-making packages.\n\n\n\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\n\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\n\n# clean variable names (base R)\ndat <- mtcars[, c(\"mpg\", \"hp\")]\ncolnames(dat) <- c(\"Miles / Gallon\", \"Horse Power\")\ndatasummary_correlation(dat)\n\n \n\n \n \n\ntinytable_lqm5yep0ilher18ulbvk\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1 \n .\n \n\nHorse Power \n -.78\n 1\n \n\n\n\n\n \n\n# clean variable names (tidyverse)\nlibrary(tidyverse)\ndat <- mtcars %>%\n select(`Miles / Gallon` = mpg,\n `Horse Power` = hp)\ndatasummary_correlation(dat)\n\n \n\n \n \n\ntinytable_3kclndgxea7xtjuujcpi\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1 \n .\n \n\nHorse Power \n -.78\n 1\n \n\n\n\n\n \n\n# alternative methods\ndatasummary_correlation(dat, method = \"pearspear\")\n\n \n\n \n \n\ntinytable_dz0p5x5la5zv0nyf1slh\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1 \n -.78\n \n\nHorse Power \n -.89\n 1 \n \n\n\n\n\n \n\n# custom function\ncor_fun <- function(x) cor(x, method = \"kendall\")\ndatasummary_correlation(dat, method = cor_fun)\n\n \n\n \n \n\ntinytable_smtzy6r4mpzoxb0ao498\n\n\n \n\n \n Miles / Gallon\n Horse Power\n \n\n\nMiles / Gallon\n 1.00\n -.74\n \n\nHorse Power \n -.74\n 1.00\n \n\n\n\n\n \n\n# rename columns alphabetically and include a footnote for reference\nnote <- sprintf(\"(%s) %s\", letters[1:ncol(dat)], colnames(dat))\nnote <- paste(note, collapse = \"; \")\n\ncolnames(dat) <- sprintf(\"(%s)\", letters[1:ncol(dat)])\n\ndatasummary_correlation(dat, notes = note)\n\n \n\n \n \n\ntinytable_j2w1c0tbx9jr58f7almw\n\n\n \n\n \n (a)\n (b)\n \n(a) Miles / Gallon; (b) Horse Power\n\n\n(a)\n 1 \n .\n \n\n(b)\n -.78\n 1\n \n\n\n\n\n \n\n# `datasummary_correlation_format`: custom function with formatting\ndat <- mtcars[, c(\"mpg\", \"hp\", \"disp\")]\n\ncor_fun <- function(x) {\n out <- cor(x, method = \"kendall\")\n datasummary_correlation_format(\n out,\n fmt = 2,\n upper_triangle = \"x\",\n diagonal = \".\")\n}\n\ndatasummary_correlation(dat, method = cor_fun)\n\n \n\n \n \n\ntinytable_qm5ndlgshzupo12elph5\n\n\n \n\n \n mpg\n hp\n disp\n \n\n\nmpg \n . \n x \n x\n \n\nhp \n -.74\n . \n x\n \n\ndisp\n -.77\n .67\n .\n \n\n\n\n\n \n\n# use kableExtra and psych to color significant cells\nlibrary(psych)\nlibrary(kableExtra)\n\ndat <- mtcars[, c(\"vs\", \"hp\", \"gear\")]\n\ncor_fun <- function(dat) {\n # compute correlations and format them\n correlations <- data.frame(cor(dat))\n correlations <- datasummary_correlation_format(correlations, fmt = 2)\n\n # calculate pvalues using the `psych` package\n pvalues <- psych::corr.test(dat)$p\n\n # use `kableExtra::cell_spec` to color significant cells\n for (i in 1:nrow(correlations)) {\n for (j in 1:ncol(correlations)) {\n if (pvalues[i, j] < 0.05 && i != j) {\n correlations[i, j] <- cell_spec(correlations[i, j], background = \"pink\")\n }\n }\n }\n return(correlations)\n}\n\n# The `escape=FALSE` is important here!\ndatasummary_correlation(dat, method = cor_fun, escape = FALSE)\n\n \n\n \n \n\ntinytable_72vj0rbb0ntxzq78x1ey\n\n\n \n\n \n vs\n hp\n gear\n \n\n\nvs \n 1.00 \n -.72\n .21 \n \n\nhp \n -.72\n 1.00 \n -.13\n \n\ngear\n .21 \n -.13 \n 1.00", + "crumbs": [ + "Get started", + "Functions", + "`datasummary_correlation`" + ] + }, + { + "objectID": "man/get_estimates.html", + "href": "man/get_estimates.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A unified approach to extract results from a wide variety of models. For some models get_estimates attaches useful attributes to the output. You can access this information by calling the attributes function: attributes(get_estimates(model))\n\n\n\nget_estimates(\n model,\n conf_level = 0.95,\n vcov = NULL,\n shape = NULL,\n coef_rename = FALSE,\n ...\n)\n\n\n\n\n\n\n\nmodel\n\n\na single model object\n\n\n\n\nconf_level\n\n\nnumeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models.\n\n\n\n\nvcov\n\n\nrobust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):\n\n\nNULL returns the default uncertainty estimates of the model object\n\n\nstring, vector, or (named) list of strings. \"iid\", \"classical\", and \"constant\" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings \"HC\", \"HC0\", \"HC1\" (alias: \"stata\"), \"HC2\", \"HC3\" (alias: \"robust\"), \"HC4\", \"HC4m\", \"HC5\", \"HAC\", \"NeweyWest\", \"Andrews\", \"panel-corrected\", \"outer-product\", and \"weave\" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. \"BS\", \"bootstrap\", \"residual\", \"mammen\", \"webb\", \"xy\", \"wild\" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (…), but it is safer to define your own custom functions as described in the next bullet.\n\n\nfunction or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).\n\n\nformula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).\n\n\nnamed list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.\n\n\na named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.\n\n\n\n\n\n\nshape\n\n\nNULL, formula, or string which determines the shape of a table.\n\n\nNULL: Default shape with terms in rows and models in columns.\n\n\nFormula: The left side determines what appears on rows, and the right side determines what appears on columns. The formula can include one or more group identifier(s) to display related terms together, which can be useful for models with multivariate outcomes or grouped coefficients (See examples section below). The group identifier(s) must be column names produced by: get_estimates(model). The group identifier(s) can be combined with the term identifier in a single column by using the colon to represent an interaction. If an incomplete formula is supplied (e.g., ~statistic), modelsummary tries to complete it automatically. Goodness-of-fit statistics are only appended to the bottom of the table when model is on the right hand side of the formula (i.e., columns). Potential shape values include:\n\n\nterm + statistic ~ model: default\n\n\nterm ~ model + statistic: statistics in separate columns\n\n\nmodel + statistic ~ term: models in rows and terms in columns\n\n\nterm + response + statistic ~ model: term and group id in separate columns\n\n\nterm : response + statistic ~ model: term and group id in a single column\n\n\nterm ~ response\n\n\n\n\nString: \"cbind\", \"rbind\", \"rcollapse\"\n\n\n\"cbind\": side-by-side models with autmoatic spanning column headers to group models (tinytable only feature).\n\n\n\"rbind\" or \"rcollapse\": \"panels\" or \"stacks\" of regression models.\n\n\nthe models argument must be a (potentially named) nested list of models.\n\n\n\n\nUnnamed nested list with 2 panels: list(list(model1, model2), list(model3, model4))\n\n\nNamed nested list with 2 panels: list(“Panel A” = list(model1, model2), “Panel B” = list(model3, model4))\n\n\nNamed panels and named models: list(“Panel A” = list(“(I)” = model1, “(II)” = model2), “Panel B” = list(“(I)” = model3, “(II)” = model4))\n\n\n\n\n\"rbind\": Bind the rows of independent regression tables\n\n\n\"rcollapse\": Bind the rows of regression tables and create a panel at the bottom where we \"collapse\" goodness-of-fit statistics which are identical across models.\n\n\n\n\n\n\n\n\ncoef_rename\n\n\nlogical, named or unnamed character vector, or function\n\n\nLogical: TRUE renames variables based on the \"label\" attribute of each column. See the Example section below.\n\n\nUnnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.\n\n\nNamed character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c(\"hp:mpg\"=\"hp X mpg\")\n\n\nFunction: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)\n\n\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`get_estimates`" + ] + }, + { + "objectID": "man/get_estimates.html#extract-model-estimates-in-a-tidy-format.", + "href": "man/get_estimates.html#extract-model-estimates-in-a-tidy-format.", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "A unified approach to extract results from a wide variety of models. For some models get_estimates attaches useful attributes to the output. You can access this information by calling the attributes function: attributes(get_estimates(model))\n\n\n\nget_estimates(\n model,\n conf_level = 0.95,\n vcov = NULL,\n shape = NULL,\n coef_rename = FALSE,\n ...\n)\n\n\n\n\n\n\n\nmodel\n\n\na single model object\n\n\n\n\nconf_level\n\n\nnumeric value between 0 and 1. confidence level to use for confidence intervals. Setting this argument to NULL does not extract confidence intervals, which can be faster for some models.\n\n\n\n\nvcov\n\n\nrobust standard errors and other manual statistics. The vcov argument accepts six types of input (see the ‘Details’ and ‘Examples’ sections below):\n\n\nNULL returns the default uncertainty estimates of the model object\n\n\nstring, vector, or (named) list of strings. \"iid\", \"classical\", and \"constant\" are aliases for NULL, which returns the model’s default uncertainty estimates. The strings \"HC\", \"HC0\", \"HC1\" (alias: \"stata\"), \"HC2\", \"HC3\" (alias: \"robust\"), \"HC4\", \"HC4m\", \"HC5\", \"HAC\", \"NeweyWest\", \"Andrews\", \"panel-corrected\", \"outer-product\", and \"weave\" use variance-covariance matrices computed using functions from the sandwich package, or equivalent method. \"BS\", \"bootstrap\", \"residual\", \"mammen\", \"webb\", \"xy\", \"wild\" use the sandwich::vcovBS(). The behavior of those functions can (and sometimes must) be altered by passing arguments to sandwich directly from modelsummary through the ellipsis (…), but it is safer to define your own custom functions as described in the next bullet.\n\n\nfunction or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., stats::vcov, sandwich::vcovHC, function(x) vcovPC(x, cluster=“country”)).\n\n\nformula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid).\n\n\nnamed list of length(models) variance-covariance matrices with row and column names equal to the names of your coefficient estimates.\n\n\na named list of length(models) vectors with names equal to the names of your coefficient estimates. See ‘Examples’ section below. Warning: since this list of vectors can include arbitrary strings or numbers, modelsummary cannot automatically calculate p values. The stars argument may thus use incorrect significance thresholds when vcov is a list of vectors.\n\n\n\n\n\n\nshape\n\n\nNULL, formula, or string which determines the shape of a table.\n\n\nNULL: Default shape with terms in rows and models in columns.\n\n\nFormula: The left side determines what appears on rows, and the right side determines what appears on columns. The formula can include one or more group identifier(s) to display related terms together, which can be useful for models with multivariate outcomes or grouped coefficients (See examples section below). The group identifier(s) must be column names produced by: get_estimates(model). The group identifier(s) can be combined with the term identifier in a single column by using the colon to represent an interaction. If an incomplete formula is supplied (e.g., ~statistic), modelsummary tries to complete it automatically. Goodness-of-fit statistics are only appended to the bottom of the table when model is on the right hand side of the formula (i.e., columns). Potential shape values include:\n\n\nterm + statistic ~ model: default\n\n\nterm ~ model + statistic: statistics in separate columns\n\n\nmodel + statistic ~ term: models in rows and terms in columns\n\n\nterm + response + statistic ~ model: term and group id in separate columns\n\n\nterm : response + statistic ~ model: term and group id in a single column\n\n\nterm ~ response\n\n\n\n\nString: \"cbind\", \"rbind\", \"rcollapse\"\n\n\n\"cbind\": side-by-side models with autmoatic spanning column headers to group models (tinytable only feature).\n\n\n\"rbind\" or \"rcollapse\": \"panels\" or \"stacks\" of regression models.\n\n\nthe models argument must be a (potentially named) nested list of models.\n\n\n\n\nUnnamed nested list with 2 panels: list(list(model1, model2), list(model3, model4))\n\n\nNamed nested list with 2 panels: list(“Panel A” = list(model1, model2), “Panel B” = list(model3, model4))\n\n\nNamed panels and named models: list(“Panel A” = list(“(I)” = model1, “(II)” = model2), “Panel B” = list(“(I)” = model3, “(II)” = model4))\n\n\n\n\n\"rbind\": Bind the rows of independent regression tables\n\n\n\"rcollapse\": Bind the rows of regression tables and create a panel at the bottom where we \"collapse\" goodness-of-fit statistics which are identical across models.\n\n\n\n\n\n\n\n\ncoef_rename\n\n\nlogical, named or unnamed character vector, or function\n\n\nLogical: TRUE renames variables based on the \"label\" attribute of each column. See the Example section below.\n\n\nUnnamed character vector of length equal to the number of coefficients in the final table, after coef_omit is applied.\n\n\nNamed character vector: Values refer to the variable names that will appear in the table. Names refer to the original term names stored in the model object. Ex: c(\"hp:mpg\"=\"hp X mpg\")\n\n\nFunction: Accepts a character vector of the model’s term names and returns a named vector like the one described above. The modelsummary package supplies a coef_rename() function which can do common cleaning tasks: modelsummary(model, coef_rename = coef_rename)\n\n\n\n\n\n\n…\n\n\nall other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments.\n\n\nparameters::model_parameters extracts parameter estimates. Available arguments depend on model type, but include:\n\n\nstandardize, include_reference, centrality, dispersion, test, ci_method, prior, diagnostic, rope_range, power, cluster, etc.\n\n\n\n\nperformance::model_performance extracts goodness-of-fit statistics. Available arguments depend on model type, but include:\n\n\nmetrics, estimator, etc.\n\n\n\n\ntinytable::tt, kableExtra::kbl or gt::gt draw tables, depending on the value of the output argument.", + "crumbs": [ + "Get started", + "Functions", + "Utilities", + "`get_estimates`" + ] + }, + { + "objectID": "man/datasummary_balance.html", + "href": "man/datasummary_balance.html", + "title": "modelsummary: Data and Model Summaries in R", + "section": "", + "text": "Balance table: Summary statistics for different subsets of the data (e.g., control and treatment groups)\nDescription\nCreates balance tables with summary statistics for different subsets of the data (e.g., control and treatment groups). It can also be used to create summary tables for full data sets. See the Details and Examples sections below, and the vignettes on the modelsummary website:\n\n\nhttps://modelsummary.com/\n\n\nhttps://modelsummary.com/articles/datasummary.html\n\nUsage\ndatasummary_balance(\n formula,\n data,\n output = \"default\",\n fmt = fmt_decimal(digits = 1, pdigits = 3),\n title = NULL,\n notes = NULL,\n align = NULL,\n stars = FALSE,\n add_columns = NULL,\n add_rows = NULL,\n dinm = TRUE,\n dinm_statistic = \"std.error\",\n escape = TRUE,\n ...\n)\n\nArguments\n\n\n\nformula\n\n\n\n\n~1: show summary statistics for the full dataset\n\n\none-sided formula: with the \"condition\" or \"column\" variable on the right-hand side.\n\n\ntwo-side formula: with the subset of variables to summarize on the left-hand side and the condition variable on the right-hand side.\n\n\n\n\n\n\ndata\n\n\nA data.frame (or tibble). If this data includes columns called \"blocks\", \"clusters\", and/or \"weights\", the \"estimatr\" package will consider them when calculating the difference in means. If there is a weights column, the reported mean and standard errors will also be weighted.\n\n\n\n\noutput\n\n\nfilename or object type (character string)\n\n\nSupported filename extensions: .docx, .html, .tex, .md, .txt, .csv, .xlsx, .png, .jpg\n\n\nSupported object types: \"default\", \"html\", \"markdown\", \"latex\", \"latex_tabular\", \"typst\", \"data.frame\", \"tinytable\", \"gt\", \"kableExtra\", \"huxtable\", \"flextable\", \"DT\", \"jupyter\". The \"modelsummary_list\" value produces a lightweight object which can be saved and fed back to the modelsummary function.\n\n\nThe \"default\" output format can be set to \"tinytable\", \"kableExtra\", \"gt\", \"flextable\", \"huxtable\", \"DT\", or \"markdown\"\n\n\nIf the user does not choose a default value, the packages listed above are tried in sequence.\n\n\nSession-specific configuration: options(“modelsummary_factory_default” = “gt”)\n\n\nPersistent configuration: config_modelsummary(output = “markdown”)\n\n\n\n\nWarning: Users should not supply a file name to the output argument if they intend to customize the table with external packages. See the ‘Details’ section.\n\n\nLaTeX compilation requires the booktabs and siunitx packages, but siunitx can be disabled or replaced with global options. See the ‘Details’ section.\n\n\n\n\n\n\nfmt\n\n\nhow to format numeric values: integer, user-supplied function, or modelsummary function.\n\n\nInteger: Number of decimal digits\n\n\nUser-supplied functions:\n\n\nAny function which accepts a numeric vector and returns a character vector of the same length.\n\n\n\n\nmodelsummary functions:\n\n\nfmt = fmt_significant(2): Two significant digits (at the term-level)\n\n\nfmt = fmt_sprintf(“%.3f”): See ?sprintf\n\n\nfmt = fmt_identity(): unformatted raw values\n\n\n\n\n\n\n\n\ntitle\n\n\nstring\n\n\n\n\nnotes\n\n\nlist or vector of notes to append to the bottom of the table.\n\n\n\n\nalign\n\n\nA string with a number of characters equal to the number of columns in the table (e.g., align = “lcc”). Valid characters: l, c, r, d.\n\n\n\"l\": left-aligned column\n\n\n\"c\": centered column\n\n\n\"r\": right-aligned column\n\n\n\"d\": dot-aligned column. For LaTeX/PDF output, this option requires at least version 3.0.25 of the siunitx LaTeX package. See the LaTeX preamble help section below for commands to insert in your LaTeX preamble.\n\n\n\n\n\n\nstars\n\n\nto indicate statistical significance\n\n\nFALSE (default): no significance stars.\n\n\nTRUE: +=.1, =.05, =.01, =0.001\n\n\nNamed numeric vector for custom stars such as c(’*’ = .1, ‘+’ = .05)\n\n\nNote: a legend will not be inserted at the bottom of the table when the estimate or statistic arguments use \"glue strings\" with stars.\n\n\n\n\n\n\nadd_columns\n\n\na data.frame (or tibble) with the same number of rows as your main table.\n\n\n\n\nadd_rows\n\n\na data.frame (or tibble) with the same number of columns as your main table. By default, rows are appended to the bottom of the table. You can define a \"position\" attribute of integers to set the row positions. See Examples section below.\n\n\n\n\ndinm\n\n\nTRUE calculates a difference in means with uncertainty estimates. This option is only available if the estimatr package is installed. If data includes columns named \"blocks\", \"clusters\", or \"weights\", this information will be taken into account automatically by estimatr::difference_in_means.\n\n\n\n\ndinm_statistic\n\n\nstring: \"std.error\" or \"p.value\"\n\n\n\n\nescape\n\n\nboolean TRUE escapes or substitutes LaTeX/HTML characters which could prevent the file from compiling/displaying. TRUE escapes all cells, captions, and notes. Users can have more fine-grained control by setting escape=FALSE and using an external command such as: modelsummary(model, “latex”) |> tinytable::format_tt(tab, j=1:5, escape=TRUE)\n\n\n\n\n…\n\n\nall other arguments are passed through to the table-making functions tinytable::tt, kableExtra::kbl, gt::gt, DT::datatable, etc. depending on the output argument. This allows users to pass arguments directly to datasummary in order to affect the behavior of other functions behind the scenes.\n\n\nGlobal Options\nThe behavior of modelsummary can be modified by setting global options. For example:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\nThe rest of this section describes each of the options above.\n\nModel labels: default column names\n\nThese global option changes the style of the default column headers:\n\n\noptions(modelsummary_model_labels = “roman”)\n\n\noptions(modelsummary_panel_labels = “roman”)\n\n\nThe supported styles are: \"model\", \"panel\", \"arabic\", \"letters\", \"roman\", \"(arabic)\", \"(letters)\", \"(roman)\"\nThe panel-specific option is only used when shape=“rbind”\n\nTable-making packages\n\nmodelsummary supports 6 table-making packages: tinytable, kableExtra, gt, flextable, huxtable, and DT. Some of these packages have overlapping functionalities. To change the default backend used for a specific file format, you can use ’ the options function:\noptions(modelsummary_factory_html = ‘kableExtra’) options(modelsummary_factory_latex = ‘gt’) options(modelsummary_factory_word = ‘huxtable’) options(modelsummary_factory_png = ‘gt’)\n\nTable themes\n\nChange the look of tables in an automated and replicable way, using the modelsummary theming functionality. See the vignette: https://modelsummary.com/articles/appearance.html\n\n\nmodelsummary_theme_gt\n\n\nmodelsummary_theme_kableExtra\n\n\nmodelsummary_theme_huxtable\n\n\nmodelsummary_theme_flextable\n\n\nmodelsummary_theme_dataframe\n\n\n\nModel extraction functions\n\nmodelsummary can use two sets of packages to extract information from statistical models: the easystats family (performance and parameters) and broom. By default, it uses easystats first and then falls back on broom in case of failure. You can change the order of priorities or include goodness-of-fit extracted by both packages by setting:\noptions(modelsummary_get = “easystats”)\noptions(modelsummary_get = “broom”)\noptions(modelsummary_get = “all”)\n\nFormatting numeric entries\n\nBy default, LaTeX tables enclose all numeric entries in the command from the siunitx package. To prevent this behavior, or to enclose numbers in dollar signs (for LaTeX math mode), users can call:\noptions(modelsummary_format_numeric_latex = “plain”)\noptions(modelsummary_format_numeric_latex = “mathmode”)\nA similar option can be used to display numerical entries using MathJax in HTML tables:\noptions(modelsummary_format_numeric_html = “mathjax”)\n\nLaTeX preamble\n\nWhen creating LaTeX via the tinytable backend (default in version 2.0.0 and later), it is useful to include the following commands in the LaTeX preamble of your documents. Note that they are added automatically when compiling Rmarkdown or Quarto documents.\n[3]{}\nExamples\n\nlibrary(modelsummary)\n\nlibrary(modelsummary)\ndatasummary_balance(~am, mtcars)\n\n \n\n \n \n\ntinytable_axqoysufa43bdk80q4fq\n\n\n \n\n\n \n0\n1\n \n \n\n\n \n Mean\n Std. Dev.\n Mean\n Std. Dev.\n Diff. in Means\n Std. Error\n \n\n\n\nmpg \n 17.1 \n 3.8 \n 24.4 \n 6.2 \n 7.2 \n 1.9 \n \n\ncyl \n 6.9 \n 1.5 \n 5.1 \n 1.6 \n -1.9 \n 0.6 \n \n\ndisp\n 290.4\n 110.2\n 143.5\n 87.2\n -146.8\n 35.0\n \n\nhp \n 160.3\n 53.9 \n 126.8\n 84.1\n -33.4 \n 26.4\n \n\ndrat\n 3.3 \n 0.4 \n 4.0 \n 0.4 \n 0.8 \n 0.1 \n \n\nwt \n 3.8 \n 0.8 \n 2.4 \n 0.6 \n -1.4 \n 0.2 \n \n\nqsec\n 18.2 \n 1.8 \n 17.4 \n 1.8 \n -0.8 \n 0.6 \n \n\nvs \n 0.4 \n 0.5 \n 0.5 \n 0.5 \n 0.2 \n 0.2 \n \n\ngear\n 3.2 \n 0.4 \n 4.4 \n 0.5 \n 1.2 \n 0.2 \n \n\ncarb\n 2.7 \n 1.1 \n 2.9 \n 2.2 \n 0.2 \n 0.7", + "crumbs": [ + "Get started", + "Functions", + "`datsummary_balance`" + ] + } +] \ No newline at end of file diff --git a/docs/site_libs/bootstrap/bootstrap-icons.css b/docs/site_libs/bootstrap/bootstrap-icons.css new file mode 100644 index 000000000..285e4448f --- /dev/null +++ b/docs/site_libs/bootstrap/bootstrap-icons.css @@ -0,0 +1,2078 @@ +/*! + * Bootstrap Icons v1.11.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +@font-face { + font-display: block; + font-family: "bootstrap-icons"; + src: +url("./bootstrap-icons.woff?2820a3852bdb9a5832199cc61cec4e65") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } +.bi-1-circle-fill::before { content: "\f796"; } +.bi-1-circle::before { content: "\f797"; } +.bi-1-square-fill::before { content: "\f798"; } +.bi-1-square::before { content: "\f799"; } +.bi-2-circle-fill::before { content: "\f79c"; } +.bi-2-circle::before { content: "\f79d"; } +.bi-2-square-fill::before { content: "\f79e"; } +.bi-2-square::before { content: "\f79f"; } +.bi-3-circle-fill::before { content: "\f7a2"; } +.bi-3-circle::before { content: "\f7a3"; } +.bi-3-square-fill::before { content: "\f7a4"; } +.bi-3-square::before { content: "\f7a5"; } +.bi-4-circle-fill::before { content: "\f7a8"; } +.bi-4-circle::before { content: "\f7a9"; } +.bi-4-square-fill::before { content: "\f7aa"; } +.bi-4-square::before { content: "\f7ab"; } +.bi-5-circle-fill::before { content: "\f7ae"; } +.bi-5-circle::before { content: "\f7af"; } +.bi-5-square-fill::before { content: "\f7b0"; } +.bi-5-square::before { content: "\f7b1"; } +.bi-6-circle-fill::before { content: "\f7b4"; } +.bi-6-circle::before { content: "\f7b5"; } +.bi-6-square-fill::before { content: "\f7b6"; } +.bi-6-square::before { content: "\f7b7"; } +.bi-7-circle-fill::before { content: "\f7ba"; } +.bi-7-circle::before { content: "\f7bb"; } +.bi-7-square-fill::before { content: "\f7bc"; } +.bi-7-square::before { content: "\f7bd"; } +.bi-8-circle-fill::before { content: "\f7c0"; } +.bi-8-circle::before { content: "\f7c1"; } +.bi-8-square-fill::before { content: "\f7c2"; } +.bi-8-square::before { content: "\f7c3"; } +.bi-9-circle-fill::before { content: "\f7c6"; } +.bi-9-circle::before { content: "\f7c7"; } +.bi-9-square-fill::before { content: "\f7c8"; } +.bi-9-square::before { content: "\f7c9"; } +.bi-airplane-engines-fill::before { content: "\f7ca"; } +.bi-airplane-engines::before { content: "\f7cb"; } +.bi-airplane-fill::before { content: "\f7cc"; } +.bi-airplane::before { content: "\f7cd"; } +.bi-alexa::before { content: "\f7ce"; } +.bi-alipay::before { content: "\f7cf"; } +.bi-android::before { content: "\f7d0"; } +.bi-android2::before { content: "\f7d1"; } +.bi-box-fill::before { content: "\f7d2"; } +.bi-box-seam-fill::before { content: "\f7d3"; } +.bi-browser-chrome::before { content: "\f7d4"; } +.bi-browser-edge::before { content: "\f7d5"; } +.bi-browser-firefox::before { content: "\f7d6"; } +.bi-browser-safari::before { content: "\f7d7"; } +.bi-c-circle-fill::before { content: "\f7da"; } +.bi-c-circle::before { content: "\f7db"; } +.bi-c-square-fill::before { content: "\f7dc"; } +.bi-c-square::before { content: "\f7dd"; } +.bi-capsule-pill::before { content: "\f7de"; } +.bi-capsule::before { content: "\f7df"; } +.bi-car-front-fill::before { content: "\f7e0"; } +.bi-car-front::before { content: "\f7e1"; } +.bi-cassette-fill::before { content: "\f7e2"; } +.bi-cassette::before { content: "\f7e3"; } +.bi-cc-circle-fill::before { content: "\f7e6"; } +.bi-cc-circle::before { content: "\f7e7"; } +.bi-cc-square-fill::before { content: "\f7e8"; } +.bi-cc-square::before { content: "\f7e9"; } +.bi-cup-hot-fill::before { content: "\f7ea"; } +.bi-cup-hot::before { content: "\f7eb"; } +.bi-currency-rupee::before { content: "\f7ec"; } +.bi-dropbox::before { content: "\f7ed"; } +.bi-escape::before { content: "\f7ee"; } +.bi-fast-forward-btn-fill::before { content: "\f7ef"; } +.bi-fast-forward-btn::before { content: "\f7f0"; } +.bi-fast-forward-circle-fill::before { content: "\f7f1"; } +.bi-fast-forward-circle::before { content: "\f7f2"; } +.bi-fast-forward-fill::before { content: "\f7f3"; } +.bi-fast-forward::before { content: "\f7f4"; } +.bi-filetype-sql::before { content: "\f7f5"; } +.bi-fire::before { content: "\f7f6"; } +.bi-google-play::before { content: "\f7f7"; } +.bi-h-circle-fill::before { content: "\f7fa"; } +.bi-h-circle::before { content: "\f7fb"; } +.bi-h-square-fill::before { content: "\f7fc"; } +.bi-h-square::before { content: "\f7fd"; } +.bi-indent::before { content: "\f7fe"; } +.bi-lungs-fill::before { content: "\f7ff"; } +.bi-lungs::before { content: "\f800"; } +.bi-microsoft-teams::before { content: "\f801"; } +.bi-p-circle-fill::before { content: "\f804"; } +.bi-p-circle::before { content: "\f805"; } +.bi-p-square-fill::before { content: "\f806"; } +.bi-p-square::before { content: "\f807"; } +.bi-pass-fill::before { content: "\f808"; } +.bi-pass::before { content: "\f809"; } +.bi-prescription::before { content: "\f80a"; } +.bi-prescription2::before { content: "\f80b"; } +.bi-r-circle-fill::before { content: "\f80e"; } +.bi-r-circle::before { content: "\f80f"; } +.bi-r-square-fill::before { content: "\f810"; } +.bi-r-square::before { content: "\f811"; } +.bi-repeat-1::before { content: "\f812"; } +.bi-repeat::before { content: "\f813"; } +.bi-rewind-btn-fill::before { content: "\f814"; } +.bi-rewind-btn::before { content: "\f815"; } +.bi-rewind-circle-fill::before { content: "\f816"; } +.bi-rewind-circle::before { content: "\f817"; } +.bi-rewind-fill::before { content: "\f818"; } +.bi-rewind::before { content: "\f819"; } +.bi-train-freight-front-fill::before { content: "\f81a"; } +.bi-train-freight-front::before { content: "\f81b"; } +.bi-train-front-fill::before { content: "\f81c"; } +.bi-train-front::before { content: "\f81d"; } +.bi-train-lightrail-front-fill::before { content: "\f81e"; } +.bi-train-lightrail-front::before { content: "\f81f"; } +.bi-truck-front-fill::before { content: "\f820"; } +.bi-truck-front::before { content: "\f821"; } +.bi-ubuntu::before { content: "\f822"; } +.bi-unindent::before { content: "\f823"; } +.bi-unity::before { content: "\f824"; } +.bi-universal-access-circle::before { content: "\f825"; } +.bi-universal-access::before { content: "\f826"; } +.bi-virus::before { content: "\f827"; } +.bi-virus2::before { content: "\f828"; } +.bi-wechat::before { content: "\f829"; } +.bi-yelp::before { content: "\f82a"; } +.bi-sign-stop-fill::before { content: "\f82b"; } +.bi-sign-stop-lights-fill::before { content: "\f82c"; } +.bi-sign-stop-lights::before { content: "\f82d"; } +.bi-sign-stop::before { content: "\f82e"; } +.bi-sign-turn-left-fill::before { content: "\f82f"; } +.bi-sign-turn-left::before { content: "\f830"; } +.bi-sign-turn-right-fill::before { content: "\f831"; } +.bi-sign-turn-right::before { content: "\f832"; } +.bi-sign-turn-slight-left-fill::before { content: "\f833"; } +.bi-sign-turn-slight-left::before { content: "\f834"; } +.bi-sign-turn-slight-right-fill::before { content: "\f835"; } +.bi-sign-turn-slight-right::before { content: "\f836"; } +.bi-sign-yield-fill::before { content: "\f837"; } +.bi-sign-yield::before { content: "\f838"; } +.bi-ev-station-fill::before { content: "\f839"; } +.bi-ev-station::before { content: "\f83a"; } +.bi-fuel-pump-diesel-fill::before { content: "\f83b"; } +.bi-fuel-pump-diesel::before { content: "\f83c"; } +.bi-fuel-pump-fill::before { content: "\f83d"; } +.bi-fuel-pump::before { content: "\f83e"; } +.bi-0-circle-fill::before { content: "\f83f"; } +.bi-0-circle::before { content: "\f840"; } +.bi-0-square-fill::before { content: "\f841"; } +.bi-0-square::before { content: "\f842"; } +.bi-rocket-fill::before { content: "\f843"; } +.bi-rocket-takeoff-fill::before { content: "\f844"; } +.bi-rocket-takeoff::before { content: "\f845"; } +.bi-rocket::before { content: "\f846"; } +.bi-stripe::before { content: "\f847"; } +.bi-subscript::before { content: "\f848"; } +.bi-superscript::before { content: "\f849"; } +.bi-trello::before { content: "\f84a"; } +.bi-envelope-at-fill::before { content: "\f84b"; } +.bi-envelope-at::before { content: "\f84c"; } +.bi-regex::before { content: "\f84d"; } +.bi-text-wrap::before { content: "\f84e"; } +.bi-sign-dead-end-fill::before { content: "\f84f"; } +.bi-sign-dead-end::before { content: "\f850"; } +.bi-sign-do-not-enter-fill::before { content: "\f851"; } +.bi-sign-do-not-enter::before { content: "\f852"; } +.bi-sign-intersection-fill::before { content: "\f853"; } +.bi-sign-intersection-side-fill::before { content: "\f854"; } +.bi-sign-intersection-side::before { content: "\f855"; } +.bi-sign-intersection-t-fill::before { content: "\f856"; } +.bi-sign-intersection-t::before { content: "\f857"; } +.bi-sign-intersection-y-fill::before { content: "\f858"; } +.bi-sign-intersection-y::before { content: "\f859"; } +.bi-sign-intersection::before { content: "\f85a"; } +.bi-sign-merge-left-fill::before { content: "\f85b"; } +.bi-sign-merge-left::before { content: "\f85c"; } +.bi-sign-merge-right-fill::before { content: "\f85d"; } +.bi-sign-merge-right::before { content: "\f85e"; } +.bi-sign-no-left-turn-fill::before { content: "\f85f"; } +.bi-sign-no-left-turn::before { content: "\f860"; } +.bi-sign-no-parking-fill::before { content: "\f861"; } +.bi-sign-no-parking::before { content: "\f862"; } +.bi-sign-no-right-turn-fill::before { content: "\f863"; } +.bi-sign-no-right-turn::before { content: "\f864"; } +.bi-sign-railroad-fill::before { content: "\f865"; } +.bi-sign-railroad::before { content: "\f866"; } +.bi-building-add::before { content: "\f867"; } +.bi-building-check::before { content: "\f868"; } +.bi-building-dash::before { content: "\f869"; } +.bi-building-down::before { content: "\f86a"; } +.bi-building-exclamation::before { content: "\f86b"; } +.bi-building-fill-add::before { content: "\f86c"; } +.bi-building-fill-check::before { content: "\f86d"; } +.bi-building-fill-dash::before { content: "\f86e"; } +.bi-building-fill-down::before { content: "\f86f"; } +.bi-building-fill-exclamation::before { content: "\f870"; } +.bi-building-fill-gear::before { content: "\f871"; } +.bi-building-fill-lock::before { content: "\f872"; } +.bi-building-fill-slash::before { content: "\f873"; } +.bi-building-fill-up::before { content: "\f874"; } +.bi-building-fill-x::before { content: "\f875"; } +.bi-building-fill::before { content: "\f876"; } +.bi-building-gear::before { content: "\f877"; } +.bi-building-lock::before { content: "\f878"; } +.bi-building-slash::before { content: "\f879"; } +.bi-building-up::before { content: "\f87a"; } +.bi-building-x::before { content: "\f87b"; } +.bi-buildings-fill::before { content: "\f87c"; } +.bi-buildings::before { content: "\f87d"; } +.bi-bus-front-fill::before { content: "\f87e"; } +.bi-bus-front::before { content: "\f87f"; } +.bi-ev-front-fill::before { content: "\f880"; } +.bi-ev-front::before { content: "\f881"; } +.bi-globe-americas::before { content: "\f882"; } +.bi-globe-asia-australia::before { content: "\f883"; } +.bi-globe-central-south-asia::before { content: "\f884"; } +.bi-globe-europe-africa::before { content: "\f885"; } +.bi-house-add-fill::before { content: "\f886"; } +.bi-house-add::before { content: "\f887"; } +.bi-house-check-fill::before { content: "\f888"; } +.bi-house-check::before { content: "\f889"; } +.bi-house-dash-fill::before { content: "\f88a"; } +.bi-house-dash::before { content: "\f88b"; } +.bi-house-down-fill::before { content: "\f88c"; } +.bi-house-down::before { content: "\f88d"; } +.bi-house-exclamation-fill::before { content: "\f88e"; } +.bi-house-exclamation::before { content: "\f88f"; } +.bi-house-gear-fill::before { content: "\f890"; } +.bi-house-gear::before { content: "\f891"; } +.bi-house-lock-fill::before { content: "\f892"; } +.bi-house-lock::before { content: "\f893"; } +.bi-house-slash-fill::before { content: "\f894"; } +.bi-house-slash::before { content: "\f895"; } +.bi-house-up-fill::before { content: "\f896"; } +.bi-house-up::before { content: "\f897"; } +.bi-house-x-fill::before { content: "\f898"; } +.bi-house-x::before { content: "\f899"; } +.bi-person-add::before { content: "\f89a"; } +.bi-person-down::before { content: "\f89b"; } +.bi-person-exclamation::before { content: "\f89c"; } +.bi-person-fill-add::before { content: "\f89d"; } +.bi-person-fill-check::before { content: "\f89e"; } +.bi-person-fill-dash::before { content: "\f89f"; } +.bi-person-fill-down::before { content: "\f8a0"; } +.bi-person-fill-exclamation::before { content: "\f8a1"; } +.bi-person-fill-gear::before { content: "\f8a2"; } +.bi-person-fill-lock::before { content: "\f8a3"; } +.bi-person-fill-slash::before { content: "\f8a4"; } +.bi-person-fill-up::before { content: "\f8a5"; } +.bi-person-fill-x::before { content: "\f8a6"; } +.bi-person-gear::before { content: "\f8a7"; } +.bi-person-lock::before { content: "\f8a8"; } +.bi-person-slash::before { content: "\f8a9"; } +.bi-person-up::before { content: "\f8aa"; } +.bi-scooter::before { content: "\f8ab"; } +.bi-taxi-front-fill::before { content: "\f8ac"; } +.bi-taxi-front::before { content: "\f8ad"; } +.bi-amd::before { content: "\f8ae"; } +.bi-database-add::before { content: "\f8af"; } +.bi-database-check::before { content: "\f8b0"; } +.bi-database-dash::before { content: "\f8b1"; } +.bi-database-down::before { content: "\f8b2"; } +.bi-database-exclamation::before { content: "\f8b3"; } +.bi-database-fill-add::before { content: "\f8b4"; } +.bi-database-fill-check::before { content: "\f8b5"; } +.bi-database-fill-dash::before { content: "\f8b6"; } +.bi-database-fill-down::before { content: "\f8b7"; } +.bi-database-fill-exclamation::before { content: "\f8b8"; } +.bi-database-fill-gear::before { content: "\f8b9"; } +.bi-database-fill-lock::before { content: "\f8ba"; } +.bi-database-fill-slash::before { content: "\f8bb"; } +.bi-database-fill-up::before { content: "\f8bc"; } +.bi-database-fill-x::before { content: "\f8bd"; } +.bi-database-fill::before { content: "\f8be"; } +.bi-database-gear::before { content: "\f8bf"; } +.bi-database-lock::before { content: "\f8c0"; } +.bi-database-slash::before { content: "\f8c1"; } +.bi-database-up::before { content: "\f8c2"; } +.bi-database-x::before { content: "\f8c3"; } +.bi-database::before { content: "\f8c4"; } +.bi-houses-fill::before { content: "\f8c5"; } +.bi-houses::before { content: "\f8c6"; } +.bi-nvidia::before { content: "\f8c7"; } +.bi-person-vcard-fill::before { content: "\f8c8"; } +.bi-person-vcard::before { content: "\f8c9"; } +.bi-sina-weibo::before { content: "\f8ca"; } +.bi-tencent-qq::before { content: "\f8cb"; } +.bi-wikipedia::before { content: "\f8cc"; } +.bi-alphabet-uppercase::before { content: "\f2a5"; } +.bi-alphabet::before { content: "\f68a"; } +.bi-amazon::before { content: "\f68d"; } +.bi-arrows-collapse-vertical::before { content: "\f690"; } +.bi-arrows-expand-vertical::before { content: "\f695"; } +.bi-arrows-vertical::before { content: "\f698"; } +.bi-arrows::before { content: "\f6a2"; } +.bi-ban-fill::before { content: "\f6a3"; } +.bi-ban::before { content: "\f6b6"; } +.bi-bing::before { content: "\f6c2"; } +.bi-cake::before { content: "\f6e0"; } +.bi-cake2::before { content: "\f6ed"; } +.bi-cookie::before { content: "\f6ee"; } +.bi-copy::before { content: "\f759"; } +.bi-crosshair::before { content: "\f769"; } +.bi-crosshair2::before { content: "\f794"; } +.bi-emoji-astonished-fill::before { content: "\f795"; } +.bi-emoji-astonished::before { content: "\f79a"; } +.bi-emoji-grimace-fill::before { content: "\f79b"; } +.bi-emoji-grimace::before { content: "\f7a0"; } +.bi-emoji-grin-fill::before { content: "\f7a1"; } +.bi-emoji-grin::before { content: "\f7a6"; } +.bi-emoji-surprise-fill::before { content: "\f7a7"; } +.bi-emoji-surprise::before { content: "\f7ac"; } +.bi-emoji-tear-fill::before { content: "\f7ad"; } +.bi-emoji-tear::before { content: "\f7b2"; } +.bi-envelope-arrow-down-fill::before { content: "\f7b3"; } +.bi-envelope-arrow-down::before { content: "\f7b8"; } +.bi-envelope-arrow-up-fill::before { content: "\f7b9"; } +.bi-envelope-arrow-up::before { content: "\f7be"; } +.bi-feather::before { content: "\f7bf"; } +.bi-feather2::before { content: "\f7c4"; } +.bi-floppy-fill::before { content: "\f7c5"; } +.bi-floppy::before { content: "\f7d8"; } +.bi-floppy2-fill::before { content: "\f7d9"; } +.bi-floppy2::before { content: "\f7e4"; } +.bi-gitlab::before { content: "\f7e5"; } +.bi-highlighter::before { content: "\f7f8"; } +.bi-marker-tip::before { content: "\f802"; } +.bi-nvme-fill::before { content: "\f803"; } +.bi-nvme::before { content: "\f80c"; } +.bi-opencollective::before { content: "\f80d"; } +.bi-pci-card-network::before { content: "\f8cd"; } +.bi-pci-card-sound::before { content: "\f8ce"; } +.bi-radar::before { content: "\f8cf"; } +.bi-send-arrow-down-fill::before { content: "\f8d0"; } +.bi-send-arrow-down::before { content: "\f8d1"; } +.bi-send-arrow-up-fill::before { content: "\f8d2"; } +.bi-send-arrow-up::before { content: "\f8d3"; } +.bi-sim-slash-fill::before { content: "\f8d4"; } +.bi-sim-slash::before { content: "\f8d5"; } +.bi-sourceforge::before { content: "\f8d6"; } +.bi-substack::before { content: "\f8d7"; } +.bi-threads-fill::before { content: "\f8d8"; } +.bi-threads::before { content: "\f8d9"; } +.bi-transparency::before { content: "\f8da"; } +.bi-twitter-x::before { content: "\f8db"; } +.bi-type-h4::before { content: "\f8dc"; } +.bi-type-h5::before { content: "\f8dd"; } +.bi-type-h6::before { content: "\f8de"; } +.bi-backpack-fill::before { content: "\f8df"; } +.bi-backpack::before { content: "\f8e0"; } +.bi-backpack2-fill::before { content: "\f8e1"; } +.bi-backpack2::before { content: "\f8e2"; } +.bi-backpack3-fill::before { content: "\f8e3"; } +.bi-backpack3::before { content: "\f8e4"; } +.bi-backpack4-fill::before { content: "\f8e5"; } +.bi-backpack4::before { content: "\f8e6"; } +.bi-brilliance::before { content: "\f8e7"; } +.bi-cake-fill::before { content: "\f8e8"; } +.bi-cake2-fill::before { content: "\f8e9"; } +.bi-duffle-fill::before { content: "\f8ea"; } +.bi-duffle::before { content: "\f8eb"; } +.bi-exposure::before { content: "\f8ec"; } +.bi-gender-neuter::before { content: "\f8ed"; } +.bi-highlights::before { content: "\f8ee"; } +.bi-luggage-fill::before { content: "\f8ef"; } +.bi-luggage::before { content: "\f8f0"; } +.bi-mailbox-flag::before { content: "\f8f1"; } +.bi-mailbox2-flag::before { content: "\f8f2"; } +.bi-noise-reduction::before { content: "\f8f3"; } +.bi-passport-fill::before { content: "\f8f4"; } +.bi-passport::before { content: "\f8f5"; } +.bi-person-arms-up::before { content: "\f8f6"; } +.bi-person-raised-hand::before { content: "\f8f7"; } +.bi-person-standing-dress::before { content: "\f8f8"; } +.bi-person-standing::before { content: "\f8f9"; } +.bi-person-walking::before { content: "\f8fa"; } +.bi-person-wheelchair::before { content: "\f8fb"; } +.bi-shadows::before { content: "\f8fc"; } +.bi-suitcase-fill::before { content: "\f8fd"; } +.bi-suitcase-lg-fill::before { content: "\f8fe"; } +.bi-suitcase-lg::before { content: "\f8ff"; } +.bi-suitcase::before { content: "\f900"; } +.bi-suitcase2-fill::before { content: "\f901"; } +.bi-suitcase2::before { content: "\f902"; } +.bi-vignette::before { content: "\f903"; } diff --git a/docs/site_libs/bootstrap/bootstrap-icons.woff b/docs/site_libs/bootstrap/bootstrap-icons.woff new file mode 100644 index 000000000..dbeeb0556 Binary files /dev/null and b/docs/site_libs/bootstrap/bootstrap-icons.woff differ diff --git a/docs/site_libs/bootstrap/bootstrap.min.css b/docs/site_libs/bootstrap/bootstrap.min.css new file mode 100644 index 000000000..17d6692c7 --- /dev/null +++ b/docs/site_libs/bootstrap/bootstrap.min.css @@ -0,0 +1,12 @@ +@import"http://fonts.googleapis.com/css?family=Lato|Roboto|Open+Sans:400italic,700italic,400,700";@import"http://fonts.googleapis.com/css?family=Source+Code+Pro:400italic,700italic,400,700";@import"https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400&display=swap";.table{font-size:.8em}/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root,[data-bs-theme=light]{--bs-blue: #2c3e50;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #e83e8c;--bs-red: #e74c3c;--bs-orange: #fd7e14;--bs-yellow: #f39c12;--bs-green: #18bc9c;--bs-teal: #20c997;--bs-cyan: #3498db;--bs-black: #000;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-gray-100: #f8f9fa;--bs-gray-200: #ecf0f1;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #7b8a8b;--bs-gray-800: #343a40;--bs-gray-900: #212529;--bs-default: #6c757d;--bs-primary: #2c3e50;--bs-secondary: #6c757d;--bs-success: #18bc9c;--bs-info: #3498db;--bs-warning: #f39c12;--bs-danger: #e74c3c;--bs-light: #ecf0f1;--bs-dark: #7b8a8b;--bs-default-rgb: 108, 117, 125;--bs-primary-rgb: 44, 62, 80;--bs-secondary-rgb: 108, 117, 125;--bs-success-rgb: 24, 188, 156;--bs-info-rgb: 52, 152, 219;--bs-warning-rgb: 243, 156, 18;--bs-danger-rgb: 231, 76, 60;--bs-light-rgb: 236, 240, 241;--bs-dark-rgb: 123, 138, 139;--bs-primary-text-emphasis: #121920;--bs-secondary-text-emphasis: #2b2f32;--bs-success-text-emphasis: #0a4b3e;--bs-info-text-emphasis: #153d58;--bs-warning-text-emphasis: #613e07;--bs-danger-text-emphasis: #5c1e18;--bs-light-text-emphasis: #7b8a8b;--bs-dark-text-emphasis: #7b8a8b;--bs-primary-bg-subtle: #d5d8dc;--bs-secondary-bg-subtle: #e2e3e5;--bs-success-bg-subtle: #d1f2eb;--bs-info-bg-subtle: #d6eaf8;--bs-warning-bg-subtle: #fdebd0;--bs-danger-bg-subtle: #fadbd8;--bs-light-bg-subtle: #fcfcfd;--bs-dark-bg-subtle: #ced4da;--bs-primary-border-subtle: #abb2b9;--bs-secondary-border-subtle: #c4c8cb;--bs-success-border-subtle: #a3e4d7;--bs-info-border-subtle: #aed6f1;--bs-warning-border-subtle: #fad7a0;--bs-danger-border-subtle: #f5b7b1;--bs-light-border-subtle: #ecf0f1;--bs-dark-border-subtle: #adb5bd;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-font-sans-serif: "Lato";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-root-font-size: 17px;--bs-body-font-family: "Lato";--bs-body-font-size:1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #222;--bs-body-color-rgb: 34, 34, 34;--bs-body-bg: #fff;--bs-body-bg-rgb: 255, 255, 255;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0, 0, 0;--bs-secondary-color: rgba(34, 34, 34, 0.75);--bs-secondary-color-rgb: 34, 34, 34;--bs-secondary-bg: #ecf0f1;--bs-secondary-bg-rgb: 236, 240, 241;--bs-tertiary-color: rgba(34, 34, 34, 0.5);--bs-tertiary-color-rgb: 34, 34, 34;--bs-tertiary-bg: #f8f9fa;--bs-tertiary-bg-rgb: 248, 249, 250;--bs-heading-color: inherit;--bs-link-color: #5e7ca1;--bs-link-color-rgb: 94, 124, 161;--bs-link-decoration: underline;--bs-link-hover-color: #4b6381;--bs-link-hover-color-rgb: 75, 99, 129;--bs-code-color: #222;--bs-highlight-bg: #fdebd0;--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: #dee2e6;--bs-border-color-translucent: rgba(0, 0, 0, 0.175);--bs-border-radius: 0.25rem;--bs-border-radius-sm: 0.2em;--bs-border-radius-lg: 0.5rem;--bs-border-radius-xl: 1rem;--bs-border-radius-xxl: 2rem;--bs-border-radius-2xl: var(--bs-border-radius-xxl);--bs-border-radius-pill: 50rem;--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width: 0.25rem;--bs-focus-ring-opacity: 0.25;--bs-focus-ring-color: rgba(44, 62, 80, 0.25);--bs-form-valid-color: #18bc9c;--bs-form-valid-border-color: #18bc9c;--bs-form-invalid-color: #e74c3c;--bs-form-invalid-border-color: #e74c3c}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222, 226, 230;--bs-body-bg: #212529;--bs-body-bg-rgb: 33, 37, 41;--bs-emphasis-color: #fff;--bs-emphasis-color-rgb: 255, 255, 255;--bs-secondary-color: rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb: 222, 226, 230;--bs-secondary-bg: #343a40;--bs-secondary-bg-rgb: 52, 58, 64;--bs-tertiary-color: rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb: 222, 226, 230;--bs-tertiary-bg: #2b3035;--bs-tertiary-bg-rgb: 43, 48, 53;--bs-primary-text-emphasis: #808b96;--bs-secondary-text-emphasis: #a7acb1;--bs-success-text-emphasis: #74d7c4;--bs-info-text-emphasis: #85c1e9;--bs-warning-text-emphasis: #f8c471;--bs-danger-text-emphasis: #f1948a;--bs-light-text-emphasis: #f8f9fa;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: #090c10;--bs-secondary-bg-subtle: #161719;--bs-success-bg-subtle: #05261f;--bs-info-bg-subtle: #0a1e2c;--bs-warning-bg-subtle: #311f04;--bs-danger-bg-subtle: #2e0f0c;--bs-light-bg-subtle: #343a40;--bs-dark-bg-subtle: #1a1d20;--bs-primary-border-subtle: #1a2530;--bs-secondary-border-subtle: #41464b;--bs-success-border-subtle: #0e715e;--bs-info-border-subtle: #1f5b83;--bs-warning-border-subtle: #925e0b;--bs-danger-border-subtle: #8b2e24;--bs-light-border-subtle: #7b8a8b;--bs-dark-border-subtle: #343a40;--bs-heading-color: inherit;--bs-link-color: #808b96;--bs-link-hover-color: #99a2ab;--bs-link-color-rgb: 128, 139, 150;--bs-link-hover-color-rgb: 153, 162, 171;--bs-code-color: white;--bs-border-color: #7b8a8b;--bs-border-color-translucent: rgba(255, 255, 255, 0.15);--bs-form-valid-color: #74d7c4;--bs-form-valid-border-color: #74d7c4;--bs-form-invalid-color: #f1948a;--bs-form-invalid-border-color: #f1948a}*,*::before,*::after{box-sizing:border-box}:root{font-size:var(--bs-root-font-size)}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;border:0;border-top:1px solid;opacity:.25}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}h1,.h1{font-size:calc(1.325rem + 0.9vw)}@media(min-width: 1200px){h1,.h1{font-size:2rem}}h2,.h2{font-size:calc(1.29rem + 0.48vw)}@media(min-width: 1200px){h2,.h2{font-size:1.65rem}}h3,.h3{font-size:calc(1.27rem + 0.24vw)}@media(min-width: 1200px){h3,.h3{font-size:1.45rem}}h4,.h4{font-size:1.25rem}h5,.h5{font-size:1.1rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{text-decoration:underline dotted;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;-ms-text-decoration:underline dotted;-o-text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem;padding:.625rem 1.25rem;border-left:.25rem solid #ecf0f1}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}b,strong{font-weight:bolder}small,.small{font-size:0.875em}mark,.mark{padding:.1875em;background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:0.75em;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}a{color:rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}a:hover{--bs-link-color-rgb: var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:0.875em;color:#000;background-color:#f8f9fa;padding:.5rem;border:1px solid var(--bs-border-color, #dee2e6);border-radius:.25rem}pre code{background-color:rgba(0,0,0,0);font-size:inherit;color:inherit;word-break:normal}code{font-size:0.875em;color:var(--bs-code-color);background-color:#f8f9fa;border-radius:.25rem;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.4rem .4rem;font-size:0.875em;color:#fff;background-color:#222;border-radius:.2em}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:rgba(34,34,34,.75);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none !important}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + 0.3vw);line-height:inherit}@media(min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:0.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:0.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:0.875em;color:rgba(34,34,34,.75)}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;width:100%;padding-right:calc(var(--bs-gutter-x)*.5);padding-left:calc(var(--bs-gutter-x)*.5);margin-right:auto;margin-left:auto}@media(min-width: 576px){.container-sm,.container{max-width:540px}}@media(min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media(min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media(min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media(min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}:root{--bs-breakpoint-xs: 0;--bs-breakpoint-sm: 576px;--bs-breakpoint-md: 768px;--bs-breakpoint-lg: 992px;--bs-breakpoint-xl: 1200px;--bs-breakpoint-xxl: 1400px}.grid{display:grid;grid-template-rows:repeat(var(--bs-rows, 1), 1fr);grid-template-columns:repeat(var(--bs-columns, 12), 1fr);gap:var(--bs-gap, 1.5rem)}.grid .g-col-1{grid-column:auto/span 1}.grid .g-col-2{grid-column:auto/span 2}.grid .g-col-3{grid-column:auto/span 3}.grid .g-col-4{grid-column:auto/span 4}.grid .g-col-5{grid-column:auto/span 5}.grid .g-col-6{grid-column:auto/span 6}.grid .g-col-7{grid-column:auto/span 7}.grid .g-col-8{grid-column:auto/span 8}.grid .g-col-9{grid-column:auto/span 9}.grid .g-col-10{grid-column:auto/span 10}.grid .g-col-11{grid-column:auto/span 11}.grid .g-col-12{grid-column:auto/span 12}.grid .g-start-1{grid-column-start:1}.grid .g-start-2{grid-column-start:2}.grid .g-start-3{grid-column-start:3}.grid .g-start-4{grid-column-start:4}.grid .g-start-5{grid-column-start:5}.grid .g-start-6{grid-column-start:6}.grid .g-start-7{grid-column-start:7}.grid .g-start-8{grid-column-start:8}.grid .g-start-9{grid-column-start:9}.grid .g-start-10{grid-column-start:10}.grid .g-start-11{grid-column-start:11}@media(min-width: 576px){.grid .g-col-sm-1{grid-column:auto/span 1}.grid .g-col-sm-2{grid-column:auto/span 2}.grid .g-col-sm-3{grid-column:auto/span 3}.grid .g-col-sm-4{grid-column:auto/span 4}.grid .g-col-sm-5{grid-column:auto/span 5}.grid .g-col-sm-6{grid-column:auto/span 6}.grid .g-col-sm-7{grid-column:auto/span 7}.grid .g-col-sm-8{grid-column:auto/span 8}.grid .g-col-sm-9{grid-column:auto/span 9}.grid .g-col-sm-10{grid-column:auto/span 10}.grid .g-col-sm-11{grid-column:auto/span 11}.grid .g-col-sm-12{grid-column:auto/span 12}.grid .g-start-sm-1{grid-column-start:1}.grid .g-start-sm-2{grid-column-start:2}.grid .g-start-sm-3{grid-column-start:3}.grid .g-start-sm-4{grid-column-start:4}.grid .g-start-sm-5{grid-column-start:5}.grid .g-start-sm-6{grid-column-start:6}.grid .g-start-sm-7{grid-column-start:7}.grid .g-start-sm-8{grid-column-start:8}.grid .g-start-sm-9{grid-column-start:9}.grid .g-start-sm-10{grid-column-start:10}.grid .g-start-sm-11{grid-column-start:11}}@media(min-width: 768px){.grid .g-col-md-1{grid-column:auto/span 1}.grid .g-col-md-2{grid-column:auto/span 2}.grid .g-col-md-3{grid-column:auto/span 3}.grid .g-col-md-4{grid-column:auto/span 4}.grid .g-col-md-5{grid-column:auto/span 5}.grid .g-col-md-6{grid-column:auto/span 6}.grid .g-col-md-7{grid-column:auto/span 7}.grid .g-col-md-8{grid-column:auto/span 8}.grid .g-col-md-9{grid-column:auto/span 9}.grid .g-col-md-10{grid-column:auto/span 10}.grid .g-col-md-11{grid-column:auto/span 11}.grid .g-col-md-12{grid-column:auto/span 12}.grid .g-start-md-1{grid-column-start:1}.grid .g-start-md-2{grid-column-start:2}.grid .g-start-md-3{grid-column-start:3}.grid .g-start-md-4{grid-column-start:4}.grid .g-start-md-5{grid-column-start:5}.grid .g-start-md-6{grid-column-start:6}.grid .g-start-md-7{grid-column-start:7}.grid .g-start-md-8{grid-column-start:8}.grid .g-start-md-9{grid-column-start:9}.grid .g-start-md-10{grid-column-start:10}.grid .g-start-md-11{grid-column-start:11}}@media(min-width: 992px){.grid .g-col-lg-1{grid-column:auto/span 1}.grid .g-col-lg-2{grid-column:auto/span 2}.grid .g-col-lg-3{grid-column:auto/span 3}.grid .g-col-lg-4{grid-column:auto/span 4}.grid .g-col-lg-5{grid-column:auto/span 5}.grid .g-col-lg-6{grid-column:auto/span 6}.grid .g-col-lg-7{grid-column:auto/span 7}.grid .g-col-lg-8{grid-column:auto/span 8}.grid .g-col-lg-9{grid-column:auto/span 9}.grid .g-col-lg-10{grid-column:auto/span 10}.grid .g-col-lg-11{grid-column:auto/span 11}.grid .g-col-lg-12{grid-column:auto/span 12}.grid .g-start-lg-1{grid-column-start:1}.grid .g-start-lg-2{grid-column-start:2}.grid .g-start-lg-3{grid-column-start:3}.grid .g-start-lg-4{grid-column-start:4}.grid .g-start-lg-5{grid-column-start:5}.grid .g-start-lg-6{grid-column-start:6}.grid .g-start-lg-7{grid-column-start:7}.grid .g-start-lg-8{grid-column-start:8}.grid .g-start-lg-9{grid-column-start:9}.grid .g-start-lg-10{grid-column-start:10}.grid .g-start-lg-11{grid-column-start:11}}@media(min-width: 1200px){.grid .g-col-xl-1{grid-column:auto/span 1}.grid .g-col-xl-2{grid-column:auto/span 2}.grid .g-col-xl-3{grid-column:auto/span 3}.grid .g-col-xl-4{grid-column:auto/span 4}.grid .g-col-xl-5{grid-column:auto/span 5}.grid .g-col-xl-6{grid-column:auto/span 6}.grid .g-col-xl-7{grid-column:auto/span 7}.grid .g-col-xl-8{grid-column:auto/span 8}.grid .g-col-xl-9{grid-column:auto/span 9}.grid .g-col-xl-10{grid-column:auto/span 10}.grid .g-col-xl-11{grid-column:auto/span 11}.grid .g-col-xl-12{grid-column:auto/span 12}.grid .g-start-xl-1{grid-column-start:1}.grid .g-start-xl-2{grid-column-start:2}.grid .g-start-xl-3{grid-column-start:3}.grid .g-start-xl-4{grid-column-start:4}.grid .g-start-xl-5{grid-column-start:5}.grid .g-start-xl-6{grid-column-start:6}.grid .g-start-xl-7{grid-column-start:7}.grid .g-start-xl-8{grid-column-start:8}.grid .g-start-xl-9{grid-column-start:9}.grid .g-start-xl-10{grid-column-start:10}.grid .g-start-xl-11{grid-column-start:11}}@media(min-width: 1400px){.grid .g-col-xxl-1{grid-column:auto/span 1}.grid .g-col-xxl-2{grid-column:auto/span 2}.grid .g-col-xxl-3{grid-column:auto/span 3}.grid .g-col-xxl-4{grid-column:auto/span 4}.grid .g-col-xxl-5{grid-column:auto/span 5}.grid .g-col-xxl-6{grid-column:auto/span 6}.grid .g-col-xxl-7{grid-column:auto/span 7}.grid .g-col-xxl-8{grid-column:auto/span 8}.grid .g-col-xxl-9{grid-column:auto/span 9}.grid .g-col-xxl-10{grid-column:auto/span 10}.grid .g-col-xxl-11{grid-column:auto/span 11}.grid .g-col-xxl-12{grid-column:auto/span 12}.grid .g-start-xxl-1{grid-column-start:1}.grid .g-start-xxl-2{grid-column-start:2}.grid .g-start-xxl-3{grid-column-start:3}.grid .g-start-xxl-4{grid-column-start:4}.grid .g-start-xxl-5{grid-column-start:5}.grid .g-start-xxl-6{grid-column-start:6}.grid .g-start-xxl-7{grid-column-start:7}.grid .g-start-xxl-8{grid-column-start:8}.grid .g-start-xxl-9{grid-column-start:9}.grid .g-start-xxl-10{grid-column-start:10}.grid .g-start-xxl-11{grid-column-start:11}}.table{--bs-table-color-type: initial;--bs-table-bg-type: initial;--bs-table-color-state: initial;--bs-table-bg-state: initial;--bs-table-color: #222;--bs-table-bg: #fff;--bs-table-border-color: #dee2e6;--bs-table-accent-bg: transparent;--bs-table-striped-color: #222;--bs-table-striped-bg: rgba(0, 0, 0, 0.05);--bs-table-active-color: #222;--bs-table-active-bg: rgba(0, 0, 0, 0.1);--bs-table-hover-color: #222;--bs-table-hover-bg: rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;color:var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(1px*2) solid #a2a2a2}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type: var(--bs-table-striped-color);--bs-table-bg-type: var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(even){--bs-table-color-type: var(--bs-table-striped-color);--bs-table-bg-type: var(--bs-table-striped-bg)}.table-active{--bs-table-color-state: var(--bs-table-active-color);--bs-table-bg-state: var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state: var(--bs-table-hover-color);--bs-table-bg-state: var(--bs-table-hover-bg)}.table-primary{--bs-table-color: #fff;--bs-table-bg: #2c3e50;--bs-table-border-color: #415162;--bs-table-striped-bg: #374859;--bs-table-striped-color: #fff;--bs-table-active-bg: #415162;--bs-table-active-color: #fff;--bs-table-hover-bg: #3c4c5d;--bs-table-hover-color: #fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color: #fff;--bs-table-bg: #6c757d;--bs-table-border-color: #7b838a;--bs-table-striped-bg: #737c84;--bs-table-striped-color: #fff;--bs-table-active-bg: #7b838a;--bs-table-active-color: #fff;--bs-table-hover-bg: #777f87;--bs-table-hover-color: #fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color: #fff;--bs-table-bg: #18bc9c;--bs-table-border-color: #2fc3a6;--bs-table-striped-bg: #24bfa1;--bs-table-striped-color: #fff;--bs-table-active-bg: #2fc3a6;--bs-table-active-color: #fff;--bs-table-hover-bg: #29c1a3;--bs-table-hover-color: #fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color: #fff;--bs-table-bg: #3498db;--bs-table-border-color: #48a2df;--bs-table-striped-bg: #3e9ddd;--bs-table-striped-color: #fff;--bs-table-active-bg: #48a2df;--bs-table-active-color: #fff;--bs-table-hover-bg: #43a0de;--bs-table-hover-color: #fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color: #fff;--bs-table-bg: #f39c12;--bs-table-border-color: #f4a62a;--bs-table-striped-bg: #f4a11e;--bs-table-striped-color: #fff;--bs-table-active-bg: #f4a62a;--bs-table-active-color: #000;--bs-table-hover-bg: #f4a324;--bs-table-hover-color: #fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color: #fff;--bs-table-bg: #e74c3c;--bs-table-border-color: #e95e50;--bs-table-striped-bg: #e85546;--bs-table-striped-color: #fff;--bs-table-active-bg: #e95e50;--bs-table-active-color: #fff;--bs-table-hover-bg: #e9594b;--bs-table-hover-color: #fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color: #000;--bs-table-bg: #ecf0f1;--bs-table-border-color: #d4d8d9;--bs-table-striped-bg: #e0e4e5;--bs-table-striped-color: #000;--bs-table-active-bg: #d4d8d9;--bs-table-active-color: #000;--bs-table-hover-bg: #dadedf;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color: #fff;--bs-table-bg: #7b8a8b;--bs-table-border-color: #889697;--bs-table-striped-bg: #829091;--bs-table-striped-color: #fff;--bs-table-active-bg: #889697;--bs-table-active-color: #fff;--bs-table-hover-bg: #859394;--bs-table-hover-color: #fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width: 575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label,.shiny-input-container .control-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.875rem}.form-text{margin-top:.25rem;font-size:0.875em;color:rgba(34,34,34,.75)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#222;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#fff;background-clip:padding-box;border:1px solid #dee2e6;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#222;background-color:#fff;border-color:#969fa8;outline:0;box-shadow:0 0 0 .25rem rgba(44,62,80,.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:rgba(34,34,34,.75);opacity:1}.form-control:disabled{background-color:#ecf0f1;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-0.375rem -0.75rem;margin-inline-end:.75rem;color:#222;background-color:#f8f9fa;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#ecf0f1}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#222;background-color:rgba(0,0,0,0);border:solid rgba(0,0,0,0);border-width:1px 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + 0.5rem + calc(1px * 2));padding:.25rem .5rem;font-size:0.875rem;border-radius:.2em}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-0.25rem -0.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(1px * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-0.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + 0.75rem + calc(1px * 2))}textarea.form-control-sm{min-height:calc(1.5em + 0.5rem + calc(1px * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(1px * 2))}.form-control-color{width:3rem;height:calc(1.5em + 0.75rem + calc(1px * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0 !important;border-radius:.25rem}.form-control-color::-webkit-color-swatch{border:0 !important;border-radius:.25rem}.form-control-color.form-control-sm{height:calc(1.5em + 0.5rem + calc(1px * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(1px * 2))}.form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#222;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#fff;background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #dee2e6;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-select{transition:none}}.form-select:focus{border-color:#969fa8;outline:0;box-shadow:0 0 0 .25rem rgba(44,62,80,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#ecf0f1}.form-select:-moz-focusring{color:rgba(0,0,0,0);text-shadow:0 0 0 #222}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:0.875rem;border-radius:.2em}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:.5rem}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check,.shiny-input-container .checkbox,.shiny-input-container .radio{display:block;min-height:1.5rem;padding-left:0;margin-bottom:.125rem}.form-check .form-check-input,.form-check .shiny-input-container .checkbox input,.form-check .shiny-input-container .radio input,.shiny-input-container .checkbox .form-check-input,.shiny-input-container .checkbox .shiny-input-container .checkbox input,.shiny-input-container .checkbox .shiny-input-container .radio input,.shiny-input-container .radio .form-check-input,.shiny-input-container .radio .shiny-input-container .checkbox input,.shiny-input-container .radio .shiny-input-container .radio input{float:left;margin-left:0}.form-check-reverse{padding-right:0;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:0;margin-left:0}.form-check-input,.shiny-input-container .checkbox input,.shiny-input-container .checkbox-inline input,.shiny-input-container .radio input,.shiny-input-container .radio-inline input{--bs-form-check-bg: #fff;width:1em;height:1em;margin-top:.25em;vertical-align:top;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid #dee2e6;print-color-adjust:exact}.form-check-input[type=checkbox],.shiny-input-container .checkbox input[type=checkbox],.shiny-input-container .checkbox-inline input[type=checkbox],.shiny-input-container .radio input[type=checkbox],.shiny-input-container .radio-inline input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio],.shiny-input-container .checkbox input[type=radio],.shiny-input-container .checkbox-inline input[type=radio],.shiny-input-container .radio input[type=radio],.shiny-input-container .radio-inline input[type=radio]{border-radius:50%}.form-check-input:active,.shiny-input-container .checkbox input:active,.shiny-input-container .checkbox-inline input:active,.shiny-input-container .radio input:active,.shiny-input-container .radio-inline input:active{filter:brightness(90%)}.form-check-input:focus,.shiny-input-container .checkbox input:focus,.shiny-input-container .checkbox-inline input:focus,.shiny-input-container .radio input:focus,.shiny-input-container .radio-inline input:focus{border-color:#969fa8;outline:0;box-shadow:0 0 0 .25rem rgba(44,62,80,.25)}.form-check-input:checked,.shiny-input-container .checkbox input:checked,.shiny-input-container .checkbox-inline input:checked,.shiny-input-container .radio input:checked,.shiny-input-container .radio-inline input:checked{background-color:#2c3e50;border-color:#2c3e50}.form-check-input:checked[type=checkbox],.shiny-input-container .checkbox input:checked[type=checkbox],.shiny-input-container .checkbox-inline input:checked[type=checkbox],.shiny-input-container .radio input:checked[type=checkbox],.shiny-input-container .radio-inline input:checked[type=checkbox]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio],.shiny-input-container .checkbox input:checked[type=radio],.shiny-input-container .checkbox-inline input:checked[type=radio],.shiny-input-container .radio input:checked[type=radio],.shiny-input-container .radio-inline input:checked[type=radio]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate,.shiny-input-container .checkbox input[type=checkbox]:indeterminate,.shiny-input-container .checkbox-inline input[type=checkbox]:indeterminate,.shiny-input-container .radio input[type=checkbox]:indeterminate,.shiny-input-container .radio-inline input[type=checkbox]:indeterminate{background-color:#2c3e50;border-color:#2c3e50;--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled,.shiny-input-container .checkbox input:disabled,.shiny-input-container .checkbox-inline input:disabled,.shiny-input-container .radio input:disabled,.shiny-input-container .radio-inline input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input[disabled]~span,.form-check-input:disabled~.form-check-label,.form-check-input:disabled~span,.shiny-input-container .checkbox input[disabled]~.form-check-label,.shiny-input-container .checkbox input[disabled]~span,.shiny-input-container .checkbox input:disabled~.form-check-label,.shiny-input-container .checkbox input:disabled~span,.shiny-input-container .checkbox-inline input[disabled]~.form-check-label,.shiny-input-container .checkbox-inline input[disabled]~span,.shiny-input-container .checkbox-inline input:disabled~.form-check-label,.shiny-input-container .checkbox-inline input:disabled~span,.shiny-input-container .radio input[disabled]~.form-check-label,.shiny-input-container .radio input[disabled]~span,.shiny-input-container .radio input:disabled~.form-check-label,.shiny-input-container .radio input:disabled~span,.shiny-input-container .radio-inline input[disabled]~.form-check-label,.shiny-input-container .radio-inline input[disabled]~span,.shiny-input-container .radio-inline input:disabled~.form-check-label,.shiny-input-container .radio-inline input:disabled~span{cursor:default;opacity:.5}.form-check-label,.shiny-input-container .checkbox label,.shiny-input-container .checkbox-inline label,.shiny-input-container .radio label,.shiny-input-container .radio-inline label{cursor:pointer}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23969fa8'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:rgba(0,0,0,0)}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(44,62,80,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(44,62,80,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#2c3e50;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#c0c5cb}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#f8f9fa;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#2c3e50;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#c0c5cb}.form-range::-moz-range-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#f8f9fa;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:rgba(34,34,34,.75)}.form-range:disabled::-moz-range-thumb{background-color:rgba(34,34,34,.75)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(1px * 2));min-height:calc(3.5rem + calc(1px * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;height:100%;padding:1rem .75rem;overflow:hidden;text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:1px solid rgba(0,0,0,0);transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control::placeholder,.form-floating>.form-control-plaintext::placeholder{color:rgba(0,0,0,0)}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown),.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill,.form-floating>.form-control-plaintext:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-control-plaintext~label,.form-floating>.form-select~label{color:rgba(var(--bs-body-color-rgb), 0.65);transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control:focus~label::after,.form-floating>.form-control:not(:placeholder-shown)~label::after,.form-floating>.form-control-plaintext~label::after,.form-floating>.form-select~label::after{position:absolute;inset:1rem .375rem;z-index:-1;height:1.5em;content:"";background-color:#fff;border-radius:.25rem}.form-floating>.form-control:-webkit-autofill~label{color:rgba(var(--bs-body-color-rgb), 0.65);transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control-plaintext~label{border-width:1px 0}.form-floating>:disabled~label,.form-floating>.form-control:disabled~label{color:#6c757d}.form-floating>:disabled~label::after,.form-floating>.form-control:disabled~label::after{background-color:#ecf0f1}.input-group{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:stretch;-webkit-align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-floating{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus,.input-group>.form-floating:focus-within{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#222;text-align:center;white-space:nowrap;background-color:#f8f9fa;border:1px solid #dee2e6;border-radius:.25rem}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.25rem .5rem;font-size:0.875rem;border-radius:.2em}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(1px*-1);border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#18bc9c}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:#18bc9c;border-radius:.25rem}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#18bc9c;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2318bc9c' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#18bc9c;box-shadow:0 0 0 .25rem rgba(24,188,156,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#18bc9c}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2318bc9c' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#18bc9c;box-shadow:0 0 0 .25rem rgba(24,188,156,.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:calc(3rem + calc(1.5em + 0.75rem))}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#18bc9c}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#18bc9c}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(24,188,156,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#18bc9c}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):valid,.input-group>.form-control:not(:focus).is-valid,.was-validated .input-group>.form-select:not(:focus):valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.input-group>.form-floating:not(:focus-within).is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#e74c3c}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:#e74c3c;border-radius:.25rem}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#e74c3c;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23e74c3c'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23e74c3c' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#e74c3c;box-shadow:0 0 0 .25rem rgba(231,76,60,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#e74c3c}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23e74c3c'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23e74c3c' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#e74c3c;box-shadow:0 0 0 .25rem rgba(231,76,60,.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid{width:calc(3rem + calc(1.5em + 0.75rem))}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#e74c3c}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#e74c3c}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(231,76,60,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#e74c3c}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):invalid,.input-group>.form-control:not(:focus).is-invalid,.was-validated .input-group>.form-select:not(:focus):invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.input-group>.form-floating:not(:focus-within).is-invalid{z-index:4}.btn{--bs-btn-padding-x: 0.75rem;--bs-btn-padding-y: 0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: #222;--bs-btn-bg: transparent;--bs-btn-border-width: 1px;--bs-btn-border-color: transparent;--bs-btn-border-radius: 0.25rem;--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity: 0.65;--bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;vertical-align:middle;cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,:not(.btn-check)+.btn:active,.btn:first-child:active,.btn.active,.btn.show{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,:not(.btn-check)+.btn:active:focus-visible,.btn:first-child:active:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-default{--bs-btn-color: #fff;--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #5c636a;--bs-btn-hover-border-color: #565e64;--bs-btn-focus-shadow-rgb: 130, 138, 145;--bs-btn-active-color: #fff;--bs-btn-active-bg: #565e64;--bs-btn-active-border-color: #51585e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #2c3e50;--bs-btn-border-color: #2c3e50;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #253544;--bs-btn-hover-border-color: #233240;--bs-btn-focus-shadow-rgb: 76, 91, 106;--bs-btn-active-color: #fff;--bs-btn-active-bg: #233240;--bs-btn-active-border-color: #212f3c;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #2c3e50;--bs-btn-disabled-border-color: #2c3e50}.btn-secondary{--bs-btn-color: #fff;--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #5c636a;--bs-btn-hover-border-color: #565e64;--bs-btn-focus-shadow-rgb: 130, 138, 145;--bs-btn-active-color: #fff;--bs-btn-active-bg: #565e64;--bs-btn-active-border-color: #51585e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}.btn-success{--bs-btn-color: #fff;--bs-btn-bg: #18bc9c;--bs-btn-border-color: #18bc9c;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #14a085;--bs-btn-hover-border-color: #13967d;--bs-btn-focus-shadow-rgb: 59, 198, 171;--bs-btn-active-color: #fff;--bs-btn-active-bg: #13967d;--bs-btn-active-border-color: #128d75;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #18bc9c;--bs-btn-disabled-border-color: #18bc9c}.btn-info{--bs-btn-color: #fff;--bs-btn-bg: #3498db;--bs-btn-border-color: #3498db;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #2c81ba;--bs-btn-hover-border-color: #2a7aaf;--bs-btn-focus-shadow-rgb: 82, 167, 224;--bs-btn-active-color: #fff;--bs-btn-active-bg: #2a7aaf;--bs-btn-active-border-color: #2772a4;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #3498db;--bs-btn-disabled-border-color: #3498db}.btn-warning{--bs-btn-color: #fff;--bs-btn-bg: #f39c12;--bs-btn-border-color: #f39c12;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #cf850f;--bs-btn-hover-border-color: #c27d0e;--bs-btn-focus-shadow-rgb: 245, 171, 54;--bs-btn-active-color: #fff;--bs-btn-active-bg: #c27d0e;--bs-btn-active-border-color: #b6750e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #f39c12;--bs-btn-disabled-border-color: #f39c12}.btn-danger{--bs-btn-color: #fff;--bs-btn-bg: #e74c3c;--bs-btn-border-color: #e74c3c;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #c44133;--bs-btn-hover-border-color: #b93d30;--bs-btn-focus-shadow-rgb: 235, 103, 89;--bs-btn-active-color: #fff;--bs-btn-active-bg: #b93d30;--bs-btn-active-border-color: #ad392d;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #e74c3c;--bs-btn-disabled-border-color: #e74c3c}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #ecf0f1;--bs-btn-border-color: #ecf0f1;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #c9cccd;--bs-btn-hover-border-color: #bdc0c1;--bs-btn-focus-shadow-rgb: 201, 204, 205;--bs-btn-active-color: #000;--bs-btn-active-bg: #bdc0c1;--bs-btn-active-border-color: #b1b4b5;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #ecf0f1;--bs-btn-disabled-border-color: #ecf0f1}.btn-dark{--bs-btn-color: #fff;--bs-btn-bg: #7b8a8b;--bs-btn-border-color: #7b8a8b;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #8f9c9c;--bs-btn-hover-border-color: #889697;--bs-btn-focus-shadow-rgb: 143, 156, 156;--bs-btn-active-color: #fff;--bs-btn-active-bg: #95a1a2;--bs-btn-active-border-color: #889697;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #7b8a8b;--bs-btn-disabled-border-color: #7b8a8b}.btn-outline-default{--bs-btn-color: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #6c757d;--bs-btn-hover-border-color: #6c757d;--bs-btn-focus-shadow-rgb: 108, 117, 125;--bs-btn-active-color: #fff;--bs-btn-active-bg: #6c757d;--bs-btn-active-border-color: #6c757d;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #6c757d;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-primary{--bs-btn-color: #2c3e50;--bs-btn-border-color: #2c3e50;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #2c3e50;--bs-btn-hover-border-color: #2c3e50;--bs-btn-focus-shadow-rgb: 44, 62, 80;--bs-btn-active-color: #fff;--bs-btn-active-bg: #2c3e50;--bs-btn-active-border-color: #2c3e50;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #2c3e50;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #2c3e50;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-secondary{--bs-btn-color: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #6c757d;--bs-btn-hover-border-color: #6c757d;--bs-btn-focus-shadow-rgb: 108, 117, 125;--bs-btn-active-color: #fff;--bs-btn-active-bg: #6c757d;--bs-btn-active-border-color: #6c757d;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #6c757d;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-success{--bs-btn-color: #18bc9c;--bs-btn-border-color: #18bc9c;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #18bc9c;--bs-btn-hover-border-color: #18bc9c;--bs-btn-focus-shadow-rgb: 24, 188, 156;--bs-btn-active-color: #fff;--bs-btn-active-bg: #18bc9c;--bs-btn-active-border-color: #18bc9c;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #18bc9c;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #18bc9c;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-info{--bs-btn-color: #3498db;--bs-btn-border-color: #3498db;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #3498db;--bs-btn-hover-border-color: #3498db;--bs-btn-focus-shadow-rgb: 52, 152, 219;--bs-btn-active-color: #fff;--bs-btn-active-bg: #3498db;--bs-btn-active-border-color: #3498db;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #3498db;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #3498db;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-warning{--bs-btn-color: #f39c12;--bs-btn-border-color: #f39c12;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #f39c12;--bs-btn-hover-border-color: #f39c12;--bs-btn-focus-shadow-rgb: 243, 156, 18;--bs-btn-active-color: #fff;--bs-btn-active-bg: #f39c12;--bs-btn-active-border-color: #f39c12;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #f39c12;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #f39c12;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-danger{--bs-btn-color: #e74c3c;--bs-btn-border-color: #e74c3c;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #e74c3c;--bs-btn-hover-border-color: #e74c3c;--bs-btn-focus-shadow-rgb: 231, 76, 60;--bs-btn-active-color: #fff;--bs-btn-active-bg: #e74c3c;--bs-btn-active-border-color: #e74c3c;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #e74c3c;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #e74c3c;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-light{--bs-btn-color: #ecf0f1;--bs-btn-border-color: #ecf0f1;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #ecf0f1;--bs-btn-hover-border-color: #ecf0f1;--bs-btn-focus-shadow-rgb: 236, 240, 241;--bs-btn-active-color: #000;--bs-btn-active-bg: #ecf0f1;--bs-btn-active-border-color: #ecf0f1;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ecf0f1;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #ecf0f1;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-dark{--bs-btn-color: #7b8a8b;--bs-btn-border-color: #7b8a8b;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #7b8a8b;--bs-btn-hover-border-color: #7b8a8b;--bs-btn-focus-shadow-rgb: 123, 138, 139;--bs-btn-active-color: #fff;--bs-btn-active-bg: #7b8a8b;--bs-btn-active-border-color: #7b8a8b;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #7b8a8b;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #7b8a8b;--bs-btn-bg: transparent;--bs-gradient: none}.btn-link{--bs-btn-font-weight: 400;--bs-btn-color: #5e7ca1;--bs-btn-bg: transparent;--bs-btn-border-color: transparent;--bs-btn-hover-color: #4b6381;--bs-btn-hover-border-color: transparent;--bs-btn-active-color: #4b6381;--bs-btn-active-border-color: transparent;--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-border-color: transparent;--bs-btn-box-shadow: 0 0 0 #000;--bs-btn-focus-shadow-rgb: 118, 144, 175;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-lg,.btn-group-lg>.btn{--bs-btn-padding-y: 0.5rem;--bs-btn-padding-x: 1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius: 0.5rem}.btn-sm,.btn-group-sm>.btn{--bs-btn-padding-y: 0.25rem;--bs-btn-padding-x: 0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius: 0.2em}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .2s ease}@media(prefers-reduced-motion: reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion: reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart,.dropup-center,.dropdown-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid rgba(0,0,0,0);border-bottom:0;border-left:.3em solid rgba(0,0,0,0)}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex: 1000;--bs-dropdown-min-width: 10rem;--bs-dropdown-padding-x: 0;--bs-dropdown-padding-y: 0.5rem;--bs-dropdown-spacer: 0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color: #222;--bs-dropdown-bg: #fff;--bs-dropdown-border-color: rgba(0, 0, 0, 0.175);--bs-dropdown-border-radius: 0.25rem;--bs-dropdown-border-width: 1px;--bs-dropdown-inner-border-radius: calc(0.25rem - 1px);--bs-dropdown-divider-bg: rgba(0, 0, 0, 0.175);--bs-dropdown-divider-margin-y: 0.5rem;--bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-dropdown-link-color: #7b8a8b;--bs-dropdown-link-hover-color: #fff;--bs-dropdown-link-hover-bg: #2c3e50;--bs-dropdown-link-active-color: #fff;--bs-dropdown-link-active-bg: #2c3e50;--bs-dropdown-link-disabled-color: rgba(34, 34, 34, 0.5);--bs-dropdown-item-padding-x: 1rem;--bs-dropdown-item-padding-y: 0.25rem;--bs-dropdown-header-color: #6c757d;--bs-dropdown-header-padding-x: 1rem;--bs-dropdown-header-padding-y: 0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width: 576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid rgba(0,0,0,0);border-bottom:.3em solid;border-left:.3em solid rgba(0,0,0,0)}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:0;border-bottom:.3em solid rgba(0,0,0,0);border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:.3em solid;border-bottom:.3em solid rgba(0,0,0,0)}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap;background-color:rgba(0,0,0,0);border:0;border-radius:var(--bs-dropdown-item-border-radius, 0)}.dropdown-item:hover,.dropdown-item:focus{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:rgba(0,0,0,0)}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:0.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color: #dee2e6;--bs-dropdown-bg: #343a40;--bs-dropdown-border-color: rgba(0, 0, 0, 0.175);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color: #dee2e6;--bs-dropdown-link-hover-color: #fff;--bs-dropdown-divider-bg: rgba(0, 0, 0, 0.175);--bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color: #fff;--bs-dropdown-link-active-bg: #2c3e50;--bs-dropdown-link-disabled-color: #adb5bd;--bs-dropdown-header-color: #adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;justify-content:flex-start;-webkit-justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:.25rem}.btn-group>:not(.btn-check:first-child)+.btn,.btn-group>.btn-group:not(:first-child){margin-left:calc(1px*-1)}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;-webkit-flex-direction:column;align-items:flex-start;-webkit-align-items:flex-start;justify-content:center;-webkit-justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:calc(1px*-1)}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn~.btn,.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x: 2rem;--bs-nav-link-padding-y: 0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color: #5e7ca1;--bs-nav-link-hover-color: #4b6381;--bs-nav-link-disabled-color: #6c757d;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background:none;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media(prefers-reduced-motion: reduce){.nav-link{transition:none}}.nav-link:hover,.nav-link:focus{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(44,62,80,.25)}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width: 1px;--bs-nav-tabs-border-color: #ecf0f1;--bs-nav-tabs-border-radius: 0.25rem;--bs-nav-tabs-link-hover-border-color: #ecf0f1 #ecf0f1 #ecf0f1;--bs-nav-tabs-link-active-color: #000;--bs-nav-tabs-link-active-bg: #fff;--bs-nav-tabs-link-active-border-color: #dee2e6 #dee2e6 #fff;border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1*var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid rgba(0,0,0,0);border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1*var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius: 0.25rem;--bs-nav-pills-link-active-color: #fff;--bs-nav-pills-link-active-bg: #2c3e50}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap: 1rem;--bs-nav-underline-border-width: 0.125rem;--bs-nav-underline-link-active-color: #000;gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid rgba(0,0,0,0)}.nav-underline .nav-link:hover,.nav-underline .nav-link:focus{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x: 0;--bs-navbar-padding-y: 1rem;--bs-navbar-color: #222;--bs-navbar-hover-color: rgba(94, 124, 161, 0.8);--bs-navbar-disabled-color: rgba(34, 34, 34, 0.75);--bs-navbar-active-color: #5e7ca1;--bs-navbar-brand-padding-y: 0.3125rem;--bs-navbar-brand-margin-end: 1rem;--bs-navbar-brand-font-size: 1.25rem;--bs-navbar-brand-color: #222;--bs-navbar-brand-hover-color: #5e7ca1;--bs-navbar-nav-link-padding-x: 0.5rem;--bs-navbar-toggler-padding-y: 0.25;--bs-navbar-toggler-padding-x: 0;--bs-navbar-toggler-font-size: 1.25rem;--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23222' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color: rgba(34, 34, 34, 0);--bs-navbar-toggler-border-radius: 0.25rem;--bs-navbar-toggler-focus-width: 0.25rem;--bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out;position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-sm,.navbar>.container-md,.navbar>.container-lg,.navbar>.container-xl,.navbar>.container-xxl{display:flex;display:-webkit-flex;flex-wrap:inherit;-webkit-flex-wrap:inherit;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x: 0;--bs-nav-link-padding-y: 0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color: var(--bs-navbar-color);--bs-nav-link-hover-color: var(--bs-navbar-hover-color);--bs-nav-link-disabled-color: var(--bs-navbar-disabled-color);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:hover,.navbar-text a:focus{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;-webkit-flex-basis:100%;flex-grow:1;-webkit-flex-grow:1;align-items:center;-webkit-align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:rgba(0,0,0,0);border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media(prefers-reduced-motion: reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media(min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color: #222;--bs-navbar-hover-color: rgba(94, 124, 161, 0.8);--bs-navbar-disabled-color: rgba(34, 34, 34, 0.75);--bs-navbar-active-color: #5e7ca1;--bs-navbar-brand-color: #222;--bs-navbar-brand-hover-color: #5e7ca1;--bs-navbar-toggler-border-color: rgba(34, 34, 34, 0);--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23222' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23222' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y: 1rem;--bs-card-spacer-x: 1rem;--bs-card-title-spacer-y: 0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width: 1px;--bs-card-border-color: rgba(0, 0, 0, 0.175);--bs-card-border-radius: 0.25rem;--bs-card-box-shadow: ;--bs-card-inner-border-radius: calc(0.25rem - 1px);--bs-card-cap-padding-y: 0.5rem;--bs-card-cap-padding-x: 1rem;--bs-card-cap-bg: rgba(52, 58, 64, 0.25);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg: #fff;--bs-card-img-overlay-padding: 1rem;--bs-card-group-margin: 0.75rem;position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;-webkit-flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-0.5*var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-0.5*var(--bs-card-cap-padding-x));margin-bottom:calc(-1*var(--bs-card-cap-padding-y));margin-left:calc(-0.5*var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-0.5*var(--bs-card-cap-padding-x));margin-left:calc(-0.5*var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media(min-width: 576px){.card-group{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap}.card-group>.card{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion{--bs-accordion-color: #222;--bs-accordion-bg: #fff;--bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease;--bs-accordion-border-color: #dee2e6;--bs-accordion-border-width: 1px;--bs-accordion-border-radius: 0.25rem;--bs-accordion-inner-border-radius: calc(0.25rem - 1px);--bs-accordion-btn-padding-x: 1.25rem;--bs-accordion-btn-padding-y: 1rem;--bs-accordion-btn-color: #222;--bs-accordion-btn-bg: #fff;--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23222'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width: 1.25rem;--bs-accordion-btn-icon-transform: rotate(-180deg);--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23121920'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-focus-border-color: #969fa8;--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(44, 62, 80, 0.25);--bs-accordion-body-padding-x: 1.25rem;--bs-accordion-body-padding-y: 1rem;--bs-accordion-active-color: #121920;--bs-accordion-active-bg: #d5d8dc}.accordion-button{position:relative;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media(prefers-reduced-motion: reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1*var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;-webkit-flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media(prefers-reduced-motion: reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:var(--bs-accordion-btn-focus-border-color);outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button::after{--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23808b96'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23808b96'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x: 0.75rem;--bs-breadcrumb-padding-y: 0.375rem;--bs-breadcrumb-margin-bottom: 1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: 0.25rem;--bs-breadcrumb-divider-color: rgba(34, 34, 34, 0.75);--bs-breadcrumb-item-padding-x: 0.5rem;--bs-breadcrumb-item-active-color: rgba(34, 34, 34, 0.75);display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, ">") /* rtl: var(--bs-breadcrumb-divider, ">") */}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x: 0.75rem;--bs-pagination-padding-y: 0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color: #fff;--bs-pagination-bg: #18bc9c;--bs-pagination-border-width: 0;--bs-pagination-border-color: transparent;--bs-pagination-border-radius: 0.25rem;--bs-pagination-hover-color: #fff;--bs-pagination-hover-bg: #0f7864;--bs-pagination-hover-border-color: transparent;--bs-pagination-focus-color: #4b6381;--bs-pagination-focus-bg: #ecf0f1;--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(44, 62, 80, 0.25);--bs-pagination-active-color: #fff;--bs-pagination-active-bg: #0f7864;--bs-pagination-active-border-color: transparent;--bs-pagination-disabled-color: #ecf0f1;--bs-pagination-disabled-bg: #3be6c4;--bs-pagination-disabled-border-color: transparent;display:flex;display:-webkit-flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.page-link.active,.active>.page-link{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.page-link.disabled,.disabled>.page-link{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(0*-1)}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x: 1.5rem;--bs-pagination-padding-y: 0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius: 0.5rem}.pagination-sm{--bs-pagination-padding-x: 0.5rem;--bs-pagination-padding-y: 0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius: 0.2em}.badge{--bs-badge-padding-x: 0.65em;--bs-badge-padding-y: 0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight: 700;--bs-badge-color: #fff;--bs-badge-border-radius: 0.25rem;display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg: transparent;--bs-alert-padding-x: 1rem;--bs-alert-padding-y: 1rem;--bs-alert-margin-bottom: 1rem;--bs-alert-color: inherit;--bs-alert-border-color: transparent;--bs-alert-border: 1px solid var(--bs-alert-border-color);--bs-alert-border-radius: 0.25rem;--bs-alert-link-color: inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-default{--bs-alert-color: var(--bs-default-text-emphasis);--bs-alert-bg: var(--bs-default-bg-subtle);--bs-alert-border-color: var(--bs-default-border-subtle);--bs-alert-link-color: var(--bs-default-text-emphasis)}.alert-primary{--bs-alert-color: var(--bs-primary-text-emphasis);--bs-alert-bg: var(--bs-primary-bg-subtle);--bs-alert-border-color: var(--bs-primary-border-subtle);--bs-alert-link-color: var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color: var(--bs-secondary-text-emphasis);--bs-alert-bg: var(--bs-secondary-bg-subtle);--bs-alert-border-color: var(--bs-secondary-border-subtle);--bs-alert-link-color: var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color: var(--bs-success-text-emphasis);--bs-alert-bg: var(--bs-success-bg-subtle);--bs-alert-border-color: var(--bs-success-border-subtle);--bs-alert-link-color: var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color: var(--bs-info-text-emphasis);--bs-alert-bg: var(--bs-info-bg-subtle);--bs-alert-border-color: var(--bs-info-border-subtle);--bs-alert-link-color: var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color: var(--bs-warning-text-emphasis);--bs-alert-bg: var(--bs-warning-bg-subtle);--bs-alert-border-color: var(--bs-warning-border-subtle);--bs-alert-link-color: var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color: var(--bs-danger-text-emphasis);--bs-alert-bg: var(--bs-danger-bg-subtle);--bs-alert-border-color: var(--bs-danger-border-subtle);--bs-alert-link-color: var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color: var(--bs-light-text-emphasis);--bs-alert-bg: var(--bs-light-bg-subtle);--bs-alert-border-color: var(--bs-light-border-subtle);--bs-alert-link-color: var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color: var(--bs-dark-text-emphasis);--bs-alert-bg: var(--bs-dark-bg-subtle);--bs-alert-border-color: var(--bs-dark-border-subtle);--bs-alert-link-color: var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress,.progress-stacked{--bs-progress-height: 1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg: #ecf0f1;--bs-progress-border-radius: 0.25rem;--bs-progress-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-progress-bar-color: #fff;--bs-progress-bar-bg: #2c3e50;--bs-progress-bar-transition: width 0.6s ease;display:flex;display:-webkit-flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media(prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color: #222;--bs-list-group-bg: #fff;--bs-list-group-border-color: #dee2e6;--bs-list-group-border-width: 1px;--bs-list-group-border-radius: 0.25rem;--bs-list-group-item-padding-x: 1rem;--bs-list-group-item-padding-y: 0.5rem;--bs-list-group-action-color: rgba(34, 34, 34, 0.75);--bs-list-group-action-hover-color: #000;--bs-list-group-action-hover-bg: #ecf0f1;--bs-list-group-action-active-color: #222;--bs-list-group-action-active-bg: #ecf0f1;--bs-list-group-disabled-color: rgba(34, 34, 34, 0.75);--bs-list-group-disabled-bg: #ecf0f1;--bs-list-group-active-color: #fff;--bs-list-group-active-bg: #2c3e50;--bs-list-group-active-border-color: #2c3e50;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1*var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-horizontal{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media(min-width: 576px){.list-group-horizontal-sm{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 768px){.list-group-horizontal-md{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 992px){.list-group-horizontal-lg{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 1200px){.list-group-horizontal-xl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 1400px){.list-group-horizontal-xxl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-default{--bs-list-group-color: var(--bs-default-text-emphasis);--bs-list-group-bg: var(--bs-default-bg-subtle);--bs-list-group-border-color: var(--bs-default-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-default-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-default-border-subtle);--bs-list-group-active-color: var(--bs-default-bg-subtle);--bs-list-group-active-bg: var(--bs-default-text-emphasis);--bs-list-group-active-border-color: var(--bs-default-text-emphasis)}.list-group-item-primary{--bs-list-group-color: var(--bs-primary-text-emphasis);--bs-list-group-bg: var(--bs-primary-bg-subtle);--bs-list-group-border-color: var(--bs-primary-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-primary-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-primary-border-subtle);--bs-list-group-active-color: var(--bs-primary-bg-subtle);--bs-list-group-active-bg: var(--bs-primary-text-emphasis);--bs-list-group-active-border-color: var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color: var(--bs-secondary-text-emphasis);--bs-list-group-bg: var(--bs-secondary-bg-subtle);--bs-list-group-border-color: var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-secondary-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-secondary-border-subtle);--bs-list-group-active-color: var(--bs-secondary-bg-subtle);--bs-list-group-active-bg: var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color: var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color: var(--bs-success-text-emphasis);--bs-list-group-bg: var(--bs-success-bg-subtle);--bs-list-group-border-color: var(--bs-success-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-success-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-success-border-subtle);--bs-list-group-active-color: var(--bs-success-bg-subtle);--bs-list-group-active-bg: var(--bs-success-text-emphasis);--bs-list-group-active-border-color: var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color: var(--bs-info-text-emphasis);--bs-list-group-bg: var(--bs-info-bg-subtle);--bs-list-group-border-color: var(--bs-info-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-info-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-info-border-subtle);--bs-list-group-active-color: var(--bs-info-bg-subtle);--bs-list-group-active-bg: var(--bs-info-text-emphasis);--bs-list-group-active-border-color: var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color: var(--bs-warning-text-emphasis);--bs-list-group-bg: var(--bs-warning-bg-subtle);--bs-list-group-border-color: var(--bs-warning-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-warning-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-warning-border-subtle);--bs-list-group-active-color: var(--bs-warning-bg-subtle);--bs-list-group-active-bg: var(--bs-warning-text-emphasis);--bs-list-group-active-border-color: var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color: var(--bs-danger-text-emphasis);--bs-list-group-bg: var(--bs-danger-bg-subtle);--bs-list-group-border-color: var(--bs-danger-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-danger-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-danger-border-subtle);--bs-list-group-active-color: var(--bs-danger-bg-subtle);--bs-list-group-active-bg: var(--bs-danger-text-emphasis);--bs-list-group-active-border-color: var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color: var(--bs-light-text-emphasis);--bs-list-group-bg: var(--bs-light-bg-subtle);--bs-list-group-border-color: var(--bs-light-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-light-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-light-border-subtle);--bs-list-group-active-color: var(--bs-light-bg-subtle);--bs-list-group-active-bg: var(--bs-light-text-emphasis);--bs-list-group-active-border-color: var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color: var(--bs-dark-text-emphasis);--bs-list-group-bg: var(--bs-dark-bg-subtle);--bs-list-group-border-color: var(--bs-dark-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-dark-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-dark-border-subtle);--bs-list-group-active-color: var(--bs-dark-bg-subtle);--bs-list-group-active-bg: var(--bs-dark-text-emphasis);--bs-list-group-active-border-color: var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color: #fff;--bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e");--bs-btn-close-opacity: 0.4;--bs-btn-close-hover-opacity: 1;--bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(44, 62, 80, 0.25);--bs-btn-close-focus-opacity: 1;--bs-btn-close-disabled-opacity: 0.25;--bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%);box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:var(--bs-btn-close-color);background:rgba(0,0,0,0) var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.25rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{filter:var(--bs-btn-close-white-filter)}[data-bs-theme=dark] .btn-close{filter:var(--bs-btn-close-white-filter)}.toast{--bs-toast-zindex: 1090;--bs-toast-padding-x: 0.75rem;--bs-toast-padding-y: 0.5rem;--bs-toast-spacing: 1.5rem;--bs-toast-max-width: 350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg: rgba(255, 255, 255, 0.85);--bs-toast-border-width: 1px;--bs-toast-border-color: rgba(0, 0, 0, 0.175);--bs-toast-border-radius: 0.25rem;--bs-toast-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-toast-header-color: rgba(34, 34, 34, 0.75);--bs-toast-header-bg: rgba(255, 255, 255, 0.85);--bs-toast-header-border-color: rgba(0, 0, 0, 0.175);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex: 1090;position:absolute;z-index:var(--bs-toast-zindex);width:max-content;width:-webkit-max-content;width:-moz-max-content;width:-ms-max-content;width:-o-max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-0.5*var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex: 1055;--bs-modal-width: 500px;--bs-modal-padding: 1rem;--bs-modal-margin: 0.5rem;--bs-modal-color: ;--bs-modal-bg: #fff;--bs-modal-border-color: rgba(0, 0, 0, 0.175);--bs-modal-border-width: 1px;--bs-modal-border-radius: 0.5rem;--bs-modal-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-modal-inner-border-radius: calc(0.5rem - 1px);--bs-modal-header-padding-x: 1rem;--bs-modal-header-padding-y: 1rem;--bs-modal-header-padding: 1rem 1rem;--bs-modal-header-border-color: #dee2e6;--bs-modal-header-border-width: 1px;--bs-modal-title-line-height: 1.5;--bs-modal-footer-gap: 0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color: #dee2e6;--bs-modal-footer-border-width: 1px;position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0, -50px)}@media(prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin)*2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;min-height:calc(100% - var(--bs-modal-margin)*2)}.modal-content{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex: 1050;--bs-backdrop-bg: #000;--bs-backdrop-opacity: 0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y)*.5) calc(var(--bs-modal-header-padding-x)*.5);margin:calc(-0.5*var(--bs-modal-header-padding-y)) calc(-0.5*var(--bs-modal-header-padding-x)) calc(-0.5*var(--bs-modal-header-padding-y)) auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:flex-end;-webkit-justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap)*.5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap)*.5)}@media(min-width: 576px){.modal{--bs-modal-margin: 1.75rem;--bs-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width: 300px}}@media(min-width: 992px){.modal-lg,.modal-xl{--bs-modal-width: 800px}}@media(min-width: 1200px){.modal-xl{--bs-modal-width: 1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header,.modal-fullscreen-sm-down .modal-footer{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header,.modal-fullscreen-md-down .modal-footer{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header,.modal-fullscreen-lg-down .modal-footer{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header,.modal-fullscreen-xl-down .modal-footer{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header,.modal-fullscreen-xxl-down .modal-footer{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex: 1080;--bs-tooltip-max-width: 200px;--bs-tooltip-padding-x: 0.5rem;--bs-tooltip-padding-y: 0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color: #fff;--bs-tooltip-bg: #000;--bs-tooltip-border-radius: 0.25rem;--bs-tooltip-opacity: 0.9;--bs-tooltip-arrow-width: 0.8rem;--bs-tooltip-arrow-height: 0.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:"Lato";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:calc(-1*var(--bs-tooltip-arrow-height))}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width)*.5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:calc(-1*var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width)*.5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:calc(-1*var(--bs-tooltip-arrow-height))}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:calc(-1*var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width)*.5) 0 calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex: 1070;--bs-popover-max-width: 276px;--bs-popover-font-size:0.875rem;--bs-popover-bg: #fff;--bs-popover-border-width: 1px;--bs-popover-border-color: rgba(0, 0, 0, 0.175);--bs-popover-border-radius: 0.5rem;--bs-popover-inner-border-radius: calc(0.5rem - 1px);--bs-popover-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-popover-header-padding-x: 1rem;--bs-popover-header-padding-y: 0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color: inherit;--bs-popover-header-bg: #ecf0f1;--bs-popover-body-padding-x: 1rem;--bs-popover-body-padding-y: 1rem;--bs-popover-body-color: #222;--bs-popover-arrow-width: 1rem;--bs-popover-arrow-height: 0.5rem;--bs-popover-arrow-border: var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:"Lato";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:rgba(0,0,0,0);border-style:solid;border-width:0}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width)*.5) 0}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width)*.5) 0}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{border-width:0 calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-0.5*var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width)*.5) 0 calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y;-webkit-touch-action:pan-y;-moz-touch-action:pan-y;-ms-touch-action:pan-y;-o-touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;display:-webkit-flex;justify-content:center;-webkit-justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;-webkit-flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid rgba(0,0,0,0);border-bottom:10px solid rgba(0,0,0,0);opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion: reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}[data-bs-theme=dark] .carousel .carousel-control-prev-icon,[data-bs-theme=dark] .carousel .carousel-control-next-icon,[data-bs-theme=dark].carousel .carousel-control-prev-icon,[data-bs-theme=dark].carousel .carousel-control-next-icon{filter:invert(1) grayscale(100)}[data-bs-theme=dark] .carousel .carousel-indicators [data-bs-target],[data-bs-theme=dark].carousel .carousel-indicators [data-bs-target]{background-color:#000}[data-bs-theme=dark] .carousel .carousel-caption,[data-bs-theme=dark].carousel .carousel-caption{color:#000}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg) /* rtl:ignore */}}.spinner-border{--bs-spinner-width: 2rem;--bs-spinner-height: 2rem;--bs-spinner-vertical-align: -0.125em;--bs-spinner-border-width: 0.25em;--bs-spinner-animation-speed: 0.75s;--bs-spinner-animation-name: spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:rgba(0,0,0,0)}.spinner-border-sm{--bs-spinner-width: 1rem;--bs-spinner-height: 1rem;--bs-spinner-border-width: 0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width: 2rem;--bs-spinner-height: 2rem;--bs-spinner-vertical-align: -0.125em;--bs-spinner-animation-speed: 0.75s;--bs-spinner-animation-name: spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width: 1rem;--bs-spinner-height: 1rem}@media(prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed: 1.5s}}.offcanvas,.offcanvas-xxl,.offcanvas-xl,.offcanvas-lg,.offcanvas-md,.offcanvas-sm{--bs-offcanvas-zindex: 1045;--bs-offcanvas-width: 400px;--bs-offcanvas-height: 30vh;--bs-offcanvas-padding-x: 1rem;--bs-offcanvas-padding-y: 1rem;--bs-offcanvas-color: #222;--bs-offcanvas-bg: #fff;--bs-offcanvas-border-width: 1px;--bs-offcanvas-border-color: rgba(0, 0, 0, 0.175);--bs-offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-offcanvas-transition: transform 0.3s ease-in-out;--bs-offcanvas-title-line-height: 1.5}@media(max-width: 575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 575.98px)and (prefers-reduced-motion: reduce){.offcanvas-sm{transition:none}}@media(max-width: 575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.showing,.offcanvas-sm.show:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show{visibility:visible}}@media(min-width: 576px){.offcanvas-sm{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 767.98px)and (prefers-reduced-motion: reduce){.offcanvas-md{transition:none}}@media(max-width: 767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.showing,.offcanvas-md.show:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show{visibility:visible}}@media(min-width: 768px){.offcanvas-md{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 991.98px)and (prefers-reduced-motion: reduce){.offcanvas-lg{transition:none}}@media(max-width: 991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.showing,.offcanvas-lg.show:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show{visibility:visible}}@media(min-width: 992px){.offcanvas-lg{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 1199.98px)and (prefers-reduced-motion: reduce){.offcanvas-xl{transition:none}}@media(max-width: 1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.showing,.offcanvas-xl.show:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show{visibility:visible}}@media(min-width: 1200px){.offcanvas-xl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 1399.98px)and (prefers-reduced-motion: reduce){.offcanvas-xxl{transition:none}}@media(max-width: 1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.showing,.offcanvas-xxl.show:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show{visibility:visible}}@media(min-width: 1400px){.offcanvas-xxl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}@media(prefers-reduced-motion: reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.showing,.offcanvas.show:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y)*.5) calc(var(--bs-offcanvas-padding-x)*.5);margin-top:calc(-0.5*var(--bs-offcanvas-padding-y));margin-right:calc(-0.5*var(--bs-offcanvas-padding-x));margin-bottom:calc(-0.5*var(--bs-offcanvas-padding-y))}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;-webkit-flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);-webkit-mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);mask-size:200% 100%;-webkit-mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{mask-position:-200% 0%;-webkit-mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-default{color:#fff !important;background-color:RGBA(var(--bs-default-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-primary{color:#fff !important;background-color:RGBA(var(--bs-primary-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-secondary{color:#fff !important;background-color:RGBA(var(--bs-secondary-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-success{color:#fff !important;background-color:RGBA(var(--bs-success-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-info{color:#fff !important;background-color:RGBA(var(--bs-info-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-warning{color:#fff !important;background-color:RGBA(var(--bs-warning-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-danger{color:#fff !important;background-color:RGBA(var(--bs-danger-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-light{color:#000 !important;background-color:RGBA(var(--bs-light-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-dark{color:#fff !important;background-color:RGBA(var(--bs-dark-rgb), var(--bs-bg-opacity, 1)) !important}.link-default{color:RGBA(var(--bs-default-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-default-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-default:hover,.link-default:focus{color:RGBA(86, 94, 100, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)) !important}.link-primary{color:RGBA(var(--bs-primary-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-primary-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-primary:hover,.link-primary:focus{color:RGBA(35, 50, 64, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(35, 50, 64, var(--bs-link-underline-opacity, 1)) !important}.link-secondary{color:RGBA(var(--bs-secondary-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-secondary-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-secondary:hover,.link-secondary:focus{color:RGBA(86, 94, 100, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)) !important}.link-success{color:RGBA(var(--bs-success-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-success-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-success:hover,.link-success:focus{color:RGBA(19, 150, 125, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(19, 150, 125, var(--bs-link-underline-opacity, 1)) !important}.link-info{color:RGBA(var(--bs-info-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-info-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-info:hover,.link-info:focus{color:RGBA(42, 122, 175, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(42, 122, 175, var(--bs-link-underline-opacity, 1)) !important}.link-warning{color:RGBA(var(--bs-warning-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-warning-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-warning:hover,.link-warning:focus{color:RGBA(194, 125, 14, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(194, 125, 14, var(--bs-link-underline-opacity, 1)) !important}.link-danger{color:RGBA(var(--bs-danger-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-danger:hover,.link-danger:focus{color:RGBA(185, 61, 48, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(185, 61, 48, var(--bs-link-underline-opacity, 1)) !important}.link-light{color:RGBA(var(--bs-light-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-light:hover,.link-light:focus{color:RGBA(240, 243, 244, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(240, 243, 244, var(--bs-link-underline-opacity, 1)) !important}.link-dark{color:RGBA(var(--bs-dark-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-dark-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-dark:hover,.link-dark:focus{color:RGBA(98, 110, 111, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(98, 110, 111, var(--bs-link-underline-opacity, 1)) !important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-body-emphasis:hover,.link-body-emphasis:focus{color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 0.75)) !important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 0.75)) !important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0) var(--bs-focus-ring-blur, 0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;-webkit-align-items:center;text-decoration-color:rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 0.5));text-underline-offset:.25em;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;-webkit-flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media(prefers-reduced-motion: reduce){.icon-link>.bi{transition:none}}.icon-link-hover:hover>.bi,.icon-link-hover:focus-visible>.bi{transform:var(--bs-icon-link-transform, translate3d(0.25em, 0, 0))}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media(min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;display:-webkit-flex;flex-direction:row;-webkit-flex-direction:row;align-items:center;-webkit-align-items:center;align-self:stretch;-webkit-align-self:stretch}.vstack{display:flex;display:-webkit-flex;flex:1 1 auto;-webkit-flex:1 1 auto;flex-direction:column;-webkit-flex-direction:column;align-self:stretch;-webkit-align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.visually-hidden:not(caption),.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption){position:absolute !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;-webkit-align-self:stretch;width:1px;min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.object-fit-contain{object-fit:contain !important}.object-fit-cover{object-fit:cover !important}.object-fit-fill{object-fit:fill !important}.object-fit-scale{object-fit:scale-down !important}.object-fit-none{object-fit:none !important}.opacity-0{opacity:0 !important}.opacity-25{opacity:.25 !important}.opacity-50{opacity:.5 !important}.opacity-75{opacity:.75 !important}.opacity-100{opacity:1 !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.overflow-x-auto{overflow-x:auto !important}.overflow-x-hidden{overflow-x:hidden !important}.overflow-x-visible{overflow-x:visible !important}.overflow-x-scroll{overflow-x:scroll !important}.overflow-y-auto{overflow-y:auto !important}.overflow-y-hidden{overflow-y:hidden !important}.overflow-y-visible{overflow-y:visible !important}.overflow-y-scroll{overflow-y:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-inline-grid{display:inline-grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175) !important}.shadow-none{box-shadow:none !important}.focus-ring-default{--bs-focus-ring-color: rgba(var(--bs-default-rgb), var(--bs-focus-ring-opacity))}.focus-ring-primary{--bs-focus-ring-color: rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color: rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color: rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color: rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color: rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color: rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color: rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color: rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-0{border:0 !important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-top-0{border-top:0 !important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-start-0{border-left:0 !important}.border-default{--bs-border-opacity: 1;border-color:rgba(var(--bs-default-rgb), var(--bs-border-opacity)) !important}.border-primary{--bs-border-opacity: 1;border-color:rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important}.border-secondary{--bs-border-opacity: 1;border-color:rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important}.border-success{--bs-border-opacity: 1;border-color:rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important}.border-info{--bs-border-opacity: 1;border-color:rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important}.border-warning{--bs-border-opacity: 1;border-color:rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important}.border-danger{--bs-border-opacity: 1;border-color:rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important}.border-light{--bs-border-opacity: 1;border-color:rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important}.border-dark{--bs-border-opacity: 1;border-color:rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important}.border-black{--bs-border-opacity: 1;border-color:rgba(var(--bs-black-rgb), var(--bs-border-opacity)) !important}.border-white{--bs-border-opacity: 1;border-color:rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle) !important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle) !important}.border-success-subtle{border-color:var(--bs-success-border-subtle) !important}.border-info-subtle{border-color:var(--bs-info-border-subtle) !important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle) !important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle) !important}.border-light-subtle{border-color:var(--bs-light-border-subtle) !important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle) !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.border-opacity-10{--bs-border-opacity: 0.1}.border-opacity-25{--bs-border-opacity: 0.25}.border-opacity-50{--bs-border-opacity: 0.5}.border-opacity-75{--bs-border-opacity: 0.75}.border-opacity-100{--bs-border-opacity: 1}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.row-gap-0{row-gap:0 !important}.row-gap-1{row-gap:.25rem !important}.row-gap-2{row-gap:.5rem !important}.row-gap-3{row-gap:1rem !important}.row-gap-4{row-gap:1.5rem !important}.row-gap-5{row-gap:3rem !important}.column-gap-0{column-gap:0 !important}.column-gap-1{column-gap:.25rem !important}.column-gap-2{column-gap:.5rem !important}.column-gap-3{column-gap:1rem !important}.column-gap-4{column-gap:1.5rem !important}.column-gap-5{column-gap:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.325rem + 0.9vw) !important}.fs-2{font-size:calc(1.29rem + 0.48vw) !important}.fs-3{font-size:calc(1.27rem + 0.24vw) !important}.fs-4{font-size:1.25rem !important}.fs-5{font-size:1.1rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-lighter{font-weight:lighter !important}.fw-light{font-weight:300 !important}.fw-normal{font-weight:400 !important}.fw-medium{font-weight:500 !important}.fw-semibold{font-weight:600 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-default{--bs-text-opacity: 1;color:rgba(var(--bs-default-rgb), var(--bs-text-opacity)) !important}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important}.text-secondary{--bs-text-opacity: 1;color:rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important}.text-success{--bs-text-opacity: 1;color:rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important}.text-info{--bs-text-opacity: 1;color:rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important}.text-warning{--bs-text-opacity: 1;color:rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important}.text-danger{--bs-text-opacity: 1;color:rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important}.text-light{--bs-text-opacity: 1;color:rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important}.text-dark{--bs-text-opacity: 1;color:rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important}.text-black{--bs-text-opacity: 1;color:rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important}.text-white{--bs-text-opacity: 1;color:rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important}.text-body{--bs-text-opacity: 1;color:rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color) !important}.text-black-50{--bs-text-opacity: 1;color:rgba(0,0,0,.5) !important}.text-white-50{--bs-text-opacity: 1;color:rgba(255,255,255,.5) !important}.text-body-secondary{--bs-text-opacity: 1;color:var(--bs-secondary-color) !important}.text-body-tertiary{--bs-text-opacity: 1;color:var(--bs-tertiary-color) !important}.text-body-emphasis{--bs-text-opacity: 1;color:var(--bs-emphasis-color) !important}.text-reset{--bs-text-opacity: 1;color:inherit !important}.text-opacity-25{--bs-text-opacity: 0.25}.text-opacity-50{--bs-text-opacity: 0.5}.text-opacity-75{--bs-text-opacity: 0.75}.text-opacity-100{--bs-text-opacity: 1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis) !important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis) !important}.text-success-emphasis{color:var(--bs-success-text-emphasis) !important}.text-info-emphasis{color:var(--bs-info-text-emphasis) !important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis) !important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis) !important}.text-light-emphasis{color:var(--bs-light-text-emphasis) !important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis) !important}.link-opacity-10{--bs-link-opacity: 0.1}.link-opacity-10-hover:hover{--bs-link-opacity: 0.1}.link-opacity-25{--bs-link-opacity: 0.25}.link-opacity-25-hover:hover{--bs-link-opacity: 0.25}.link-opacity-50{--bs-link-opacity: 0.5}.link-opacity-50-hover:hover{--bs-link-opacity: 0.5}.link-opacity-75{--bs-link-opacity: 0.75}.link-opacity-75-hover:hover{--bs-link-opacity: 0.75}.link-opacity-100{--bs-link-opacity: 1}.link-opacity-100-hover:hover{--bs-link-opacity: 1}.link-offset-1{text-underline-offset:.125em !important}.link-offset-1-hover:hover{text-underline-offset:.125em !important}.link-offset-2{text-underline-offset:.25em !important}.link-offset-2-hover:hover{text-underline-offset:.25em !important}.link-offset-3{text-underline-offset:.375em !important}.link-offset-3-hover:hover{text-underline-offset:.375em !important}.link-underline-default{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-default-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-primary{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-primary-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-secondary{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-secondary-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-success{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-success-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-info{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-info-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-warning{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-warning-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-danger{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-danger-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-light{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-light-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-dark{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-dark-rgb), var(--bs-link-underline-opacity)) !important}.link-underline{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-link-color-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-underline-opacity-0{--bs-link-underline-opacity: 0}.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity: 0}.link-underline-opacity-10{--bs-link-underline-opacity: 0.1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity: 0.1}.link-underline-opacity-25{--bs-link-underline-opacity: 0.25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity: 0.25}.link-underline-opacity-50{--bs-link-underline-opacity: 0.5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity: 0.5}.link-underline-opacity-75{--bs-link-underline-opacity: 0.75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity: 0.75}.link-underline-opacity-100{--bs-link-underline-opacity: 1}.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity: 1}.bg-default{--bs-bg-opacity: 1;background-color:rgba(var(--bs-default-rgb), var(--bs-bg-opacity)) !important}.bg-primary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important}.bg-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important}.bg-success{--bs-bg-opacity: 1;background-color:rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important}.bg-info{--bs-bg-opacity: 1;background-color:rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important}.bg-warning{--bs-bg-opacity: 1;background-color:rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important}.bg-danger{--bs-bg-opacity: 1;background-color:rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important}.bg-light{--bs-bg-opacity: 1;background-color:rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important}.bg-dark{--bs-bg-opacity: 1;background-color:rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important}.bg-black{--bs-bg-opacity: 1;background-color:rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important}.bg-white{--bs-bg-opacity: 1;background-color:rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important}.bg-body{--bs-bg-opacity: 1;background-color:rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important}.bg-transparent{--bs-bg-opacity: 1;background-color:rgba(0,0,0,0) !important}.bg-body-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-bg-rgb), var(--bs-bg-opacity)) !important}.bg-body-tertiary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-tertiary-bg-rgb), var(--bs-bg-opacity)) !important}.bg-opacity-10{--bs-bg-opacity: 0.1}.bg-opacity-25{--bs-bg-opacity: 0.25}.bg-opacity-50{--bs-bg-opacity: 0.5}.bg-opacity-75{--bs-bg-opacity: 0.75}.bg-opacity-100{--bs-bg-opacity: 1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle) !important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle) !important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle) !important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle) !important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle) !important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle) !important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle) !important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle) !important}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:var(--bs-border-radius) !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:var(--bs-border-radius-sm) !important}.rounded-2{border-radius:var(--bs-border-radius) !important}.rounded-3{border-radius:var(--bs-border-radius-lg) !important}.rounded-4{border-radius:var(--bs-border-radius-xl) !important}.rounded-5{border-radius:var(--bs-border-radius-xxl) !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:var(--bs-border-radius-pill) !important}.rounded-top{border-top-left-radius:var(--bs-border-radius) !important;border-top-right-radius:var(--bs-border-radius) !important}.rounded-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm) !important;border-top-right-radius:var(--bs-border-radius-sm) !important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius) !important;border-top-right-radius:var(--bs-border-radius) !important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg) !important;border-top-right-radius:var(--bs-border-radius-lg) !important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl) !important;border-top-right-radius:var(--bs-border-radius-xl) !important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl) !important;border-top-right-radius:var(--bs-border-radius-xxl) !important}.rounded-top-circle{border-top-left-radius:50% !important;border-top-right-radius:50% !important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill) !important;border-top-right-radius:var(--bs-border-radius-pill) !important}.rounded-end{border-top-right-radius:var(--bs-border-radius) !important;border-bottom-right-radius:var(--bs-border-radius) !important}.rounded-end-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm) !important;border-bottom-right-radius:var(--bs-border-radius-sm) !important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius) !important;border-bottom-right-radius:var(--bs-border-radius) !important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg) !important;border-bottom-right-radius:var(--bs-border-radius-lg) !important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl) !important;border-bottom-right-radius:var(--bs-border-radius-xl) !important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl) !important;border-bottom-right-radius:var(--bs-border-radius-xxl) !important}.rounded-end-circle{border-top-right-radius:50% !important;border-bottom-right-radius:50% !important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill) !important;border-bottom-right-radius:var(--bs-border-radius-pill) !important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius) !important;border-bottom-left-radius:var(--bs-border-radius) !important}.rounded-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm) !important;border-bottom-left-radius:var(--bs-border-radius-sm) !important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius) !important;border-bottom-left-radius:var(--bs-border-radius) !important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg) !important;border-bottom-left-radius:var(--bs-border-radius-lg) !important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl) !important;border-bottom-left-radius:var(--bs-border-radius-xl) !important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl) !important;border-bottom-left-radius:var(--bs-border-radius-xxl) !important}.rounded-bottom-circle{border-bottom-right-radius:50% !important;border-bottom-left-radius:50% !important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill) !important;border-bottom-left-radius:var(--bs-border-radius-pill) !important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius) !important;border-top-left-radius:var(--bs-border-radius) !important}.rounded-start-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm) !important;border-top-left-radius:var(--bs-border-radius-sm) !important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius) !important;border-top-left-radius:var(--bs-border-radius) !important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg) !important;border-top-left-radius:var(--bs-border-radius-lg) !important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl) !important;border-top-left-radius:var(--bs-border-radius-xl) !important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl) !important;border-top-left-radius:var(--bs-border-radius-xxl) !important}.rounded-start-circle{border-bottom-left-radius:50% !important;border-top-left-radius:50% !important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill) !important;border-top-left-radius:var(--bs-border-radius-pill) !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}.z-n1{z-index:-1 !important}.z-0{z-index:0 !important}.z-1{z-index:1 !important}.z-2{z-index:2 !important}.z-3{z-index:3 !important}@media(min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.object-fit-sm-contain{object-fit:contain !important}.object-fit-sm-cover{object-fit:cover !important}.object-fit-sm-fill{object-fit:fill !important}.object-fit-sm-scale{object-fit:scale-down !important}.object-fit-sm-none{object-fit:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-inline-grid{display:inline-grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.row-gap-sm-0{row-gap:0 !important}.row-gap-sm-1{row-gap:.25rem !important}.row-gap-sm-2{row-gap:.5rem !important}.row-gap-sm-3{row-gap:1rem !important}.row-gap-sm-4{row-gap:1.5rem !important}.row-gap-sm-5{row-gap:3rem !important}.column-gap-sm-0{column-gap:0 !important}.column-gap-sm-1{column-gap:.25rem !important}.column-gap-sm-2{column-gap:.5rem !important}.column-gap-sm-3{column-gap:1rem !important}.column-gap-sm-4{column-gap:1.5rem !important}.column-gap-sm-5{column-gap:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media(min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.object-fit-md-contain{object-fit:contain !important}.object-fit-md-cover{object-fit:cover !important}.object-fit-md-fill{object-fit:fill !important}.object-fit-md-scale{object-fit:scale-down !important}.object-fit-md-none{object-fit:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-inline-grid{display:inline-grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.row-gap-md-0{row-gap:0 !important}.row-gap-md-1{row-gap:.25rem !important}.row-gap-md-2{row-gap:.5rem !important}.row-gap-md-3{row-gap:1rem !important}.row-gap-md-4{row-gap:1.5rem !important}.row-gap-md-5{row-gap:3rem !important}.column-gap-md-0{column-gap:0 !important}.column-gap-md-1{column-gap:.25rem !important}.column-gap-md-2{column-gap:.5rem !important}.column-gap-md-3{column-gap:1rem !important}.column-gap-md-4{column-gap:1.5rem !important}.column-gap-md-5{column-gap:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media(min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.object-fit-lg-contain{object-fit:contain !important}.object-fit-lg-cover{object-fit:cover !important}.object-fit-lg-fill{object-fit:fill !important}.object-fit-lg-scale{object-fit:scale-down !important}.object-fit-lg-none{object-fit:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-inline-grid{display:inline-grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.row-gap-lg-0{row-gap:0 !important}.row-gap-lg-1{row-gap:.25rem !important}.row-gap-lg-2{row-gap:.5rem !important}.row-gap-lg-3{row-gap:1rem !important}.row-gap-lg-4{row-gap:1.5rem !important}.row-gap-lg-5{row-gap:3rem !important}.column-gap-lg-0{column-gap:0 !important}.column-gap-lg-1{column-gap:.25rem !important}.column-gap-lg-2{column-gap:.5rem !important}.column-gap-lg-3{column-gap:1rem !important}.column-gap-lg-4{column-gap:1.5rem !important}.column-gap-lg-5{column-gap:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media(min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.object-fit-xl-contain{object-fit:contain !important}.object-fit-xl-cover{object-fit:cover !important}.object-fit-xl-fill{object-fit:fill !important}.object-fit-xl-scale{object-fit:scale-down !important}.object-fit-xl-none{object-fit:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-inline-grid{display:inline-grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.row-gap-xl-0{row-gap:0 !important}.row-gap-xl-1{row-gap:.25rem !important}.row-gap-xl-2{row-gap:.5rem !important}.row-gap-xl-3{row-gap:1rem !important}.row-gap-xl-4{row-gap:1.5rem !important}.row-gap-xl-5{row-gap:3rem !important}.column-gap-xl-0{column-gap:0 !important}.column-gap-xl-1{column-gap:.25rem !important}.column-gap-xl-2{column-gap:.5rem !important}.column-gap-xl-3{column-gap:1rem !important}.column-gap-xl-4{column-gap:1.5rem !important}.column-gap-xl-5{column-gap:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media(min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.object-fit-xxl-contain{object-fit:contain !important}.object-fit-xxl-cover{object-fit:cover !important}.object-fit-xxl-fill{object-fit:fill !important}.object-fit-xxl-scale{object-fit:scale-down !important}.object-fit-xxl-none{object-fit:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-inline-grid{display:inline-grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.row-gap-xxl-0{row-gap:0 !important}.row-gap-xxl-1{row-gap:.25rem !important}.row-gap-xxl-2{row-gap:.5rem !important}.row-gap-xxl-3{row-gap:1rem !important}.row-gap-xxl-4{row-gap:1.5rem !important}.row-gap-xxl-5{row-gap:3rem !important}.column-gap-xxl-0{column-gap:0 !important}.column-gap-xxl-1{column-gap:.25rem !important}.column-gap-xxl-2{column-gap:.5rem !important}.column-gap-xxl-3{column-gap:1rem !important}.column-gap-xxl-4{column-gap:1.5rem !important}.column-gap-xxl-5{column-gap:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}.bg-default{color:#fff}.bg-primary{color:#fff}.bg-secondary{color:#fff}.bg-success{color:#fff}.bg-info{color:#fff}.bg-warning{color:#fff}.bg-danger{color:#fff}.bg-light{color:#000}.bg-dark{color:#fff}@media(min-width: 1200px){.fs-1{font-size:2rem !important}.fs-2{font-size:1.65rem !important}.fs-3{font-size:1.45rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-inline-grid{display:inline-grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0}.bg-blue{--bslib-color-bg: #2c3e50;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-blue{--bslib-color-fg: #2c3e50;color:var(--bslib-color-fg)}.bg-indigo{--bslib-color-bg: #6610f2;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-indigo{--bslib-color-fg: #6610f2;color:var(--bslib-color-fg)}.bg-purple{--bslib-color-bg: #6f42c1;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-purple{--bslib-color-fg: #6f42c1;color:var(--bslib-color-fg)}.bg-pink{--bslib-color-bg: #e83e8c;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-pink{--bslib-color-fg: #e83e8c;color:var(--bslib-color-fg)}.bg-red{--bslib-color-bg: #e74c3c;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-red{--bslib-color-fg: #e74c3c;color:var(--bslib-color-fg)}.bg-orange{--bslib-color-bg: #fd7e14;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-orange{--bslib-color-fg: #fd7e14;color:var(--bslib-color-fg)}.bg-yellow{--bslib-color-bg: #f39c12;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-yellow{--bslib-color-fg: #f39c12;color:var(--bslib-color-fg)}.bg-green{--bslib-color-bg: #18bc9c;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-green{--bslib-color-fg: #18bc9c;color:var(--bslib-color-fg)}.bg-teal{--bslib-color-bg: #20c997;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-teal{--bslib-color-fg: #20c997;color:var(--bslib-color-fg)}.bg-cyan{--bslib-color-bg: #3498db;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-cyan{--bslib-color-fg: #3498db;color:var(--bslib-color-fg)}.text-default{--bslib-color-fg: #6c757d}.bg-default{--bslib-color-bg: #6c757d;--bslib-color-fg: #fff}.text-primary{--bslib-color-fg: #2c3e50}.bg-primary{--bslib-color-bg: #2c3e50;--bslib-color-fg: #fff}.text-secondary{--bslib-color-fg: #6c757d}.bg-secondary{--bslib-color-bg: #6c757d;--bslib-color-fg: #fff}.text-success{--bslib-color-fg: #18bc9c}.bg-success{--bslib-color-bg: #18bc9c;--bslib-color-fg: #fff}.text-info{--bslib-color-fg: #3498db}.bg-info{--bslib-color-bg: #3498db;--bslib-color-fg: #fff}.text-warning{--bslib-color-fg: #f39c12}.bg-warning{--bslib-color-bg: #f39c12;--bslib-color-fg: #fff}.text-danger{--bslib-color-fg: #e74c3c}.bg-danger{--bslib-color-bg: #e74c3c;--bslib-color-fg: #fff}.text-light{--bslib-color-fg: #ecf0f1}.bg-light{--bslib-color-bg: #ecf0f1;--bslib-color-fg: #000}.text-dark{--bslib-color-fg: #7b8a8b}.bg-dark{--bslib-color-bg: #7b8a8b;--bslib-color-fg: #fff}.bg-gradient-blue-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #432c91;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #432c91;color:#fff}.bg-gradient-blue-purple{--bslib-color-fg: #fff;--bslib-color-bg: #47407d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #47407d;color:#fff}.bg-gradient-blue-pink{--bslib-color-fg: #fff;--bslib-color-bg: #773e68;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #773e68;color:#fff}.bg-gradient-blue-red{--bslib-color-fg: #fff;--bslib-color-bg: #774448;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #774448;color:#fff}.bg-gradient-blue-orange{--bslib-color-fg: #fff;--bslib-color-bg: #805838;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #805838;color:#fff}.bg-gradient-blue-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #7c6437;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #7c6437;color:#fff}.bg-gradient-blue-green{--bslib-color-fg: #fff;--bslib-color-bg: #24706e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #24706e;color:#fff}.bg-gradient-blue-teal{--bslib-color-fg: #fff;--bslib-color-bg: #27766c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #27766c;color:#fff}.bg-gradient-blue-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #2f6288;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #2f6288;color:#fff}.bg-gradient-indigo-blue{--bslib-color-fg: #fff;--bslib-color-bg: #4f22b1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #4f22b1;color:#fff}.bg-gradient-indigo-purple{--bslib-color-fg: #fff;--bslib-color-bg: #6a24de;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #6a24de;color:#fff}.bg-gradient-indigo-pink{--bslib-color-fg: #fff;--bslib-color-bg: #9a22c9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #9a22c9;color:#fff}.bg-gradient-indigo-red{--bslib-color-fg: #fff;--bslib-color-bg: #9a28a9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #9a28a9;color:#fff}.bg-gradient-indigo-orange{--bslib-color-fg: #fff;--bslib-color-bg: #a23c99;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a23c99;color:#fff}.bg-gradient-indigo-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #9e4898;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #9e4898;color:#fff}.bg-gradient-indigo-green{--bslib-color-fg: #fff;--bslib-color-bg: #4755d0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #4755d0;color:#fff}.bg-gradient-indigo-teal{--bslib-color-fg: #fff;--bslib-color-bg: #4a5ace;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4a5ace;color:#fff}.bg-gradient-indigo-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #5246e9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #5246e9;color:#fff}.bg-gradient-purple-blue{--bslib-color-fg: #fff;--bslib-color-bg: #544094;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #544094;color:#fff}.bg-gradient-purple-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #6b2ed5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #6b2ed5;color:#fff}.bg-gradient-purple-pink{--bslib-color-fg: #fff;--bslib-color-bg: #9f40ac;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #9f40ac;color:#fff}.bg-gradient-purple-red{--bslib-color-fg: #fff;--bslib-color-bg: #9f468c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #9f468c;color:#fff}.bg-gradient-purple-orange{--bslib-color-fg: #fff;--bslib-color-bg: #a85a7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a85a7c;color:#fff}.bg-gradient-purple-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #a4667b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #a4667b;color:#fff}.bg-gradient-purple-green{--bslib-color-fg: #fff;--bslib-color-bg: #4c73b2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #4c73b2;color:#fff}.bg-gradient-purple-teal{--bslib-color-fg: #fff;--bslib-color-bg: #4f78b0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4f78b0;color:#fff}.bg-gradient-purple-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #5764cb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #5764cb;color:#fff}.bg-gradient-pink-blue{--bslib-color-fg: #fff;--bslib-color-bg: #9d3e74;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #9d3e74;color:#fff}.bg-gradient-pink-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #b42cb5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #b42cb5;color:#fff}.bg-gradient-pink-purple{--bslib-color-fg: #fff;--bslib-color-bg: #b840a1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #b840a1;color:#fff}.bg-gradient-pink-red{--bslib-color-fg: #fff;--bslib-color-bg: #e8446c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #e8446c;color:#fff}.bg-gradient-pink-orange{--bslib-color-fg: #fff;--bslib-color-bg: #f0585c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #f0585c;color:#fff}.bg-gradient-pink-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #ec645b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #ec645b;color:#fff}.bg-gradient-pink-green{--bslib-color-fg: #fff;--bslib-color-bg: #957092;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #957092;color:#fff}.bg-gradient-pink-teal{--bslib-color-fg: #fff;--bslib-color-bg: #987690;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #987690;color:#fff}.bg-gradient-pink-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #a062ac;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #a062ac;color:#fff}.bg-gradient-red-blue{--bslib-color-fg: #fff;--bslib-color-bg: #9c4644;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #9c4644;color:#fff}.bg-gradient-red-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #b33485;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #b33485;color:#fff}.bg-gradient-red-purple{--bslib-color-fg: #fff;--bslib-color-bg: #b74871;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #b74871;color:#fff}.bg-gradient-red-pink{--bslib-color-fg: #fff;--bslib-color-bg: #e7465c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #e7465c;color:#fff}.bg-gradient-red-orange{--bslib-color-fg: #fff;--bslib-color-bg: #f0602c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #f0602c;color:#fff}.bg-gradient-red-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #ec6c2b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #ec6c2b;color:#fff}.bg-gradient-red-green{--bslib-color-fg: #fff;--bslib-color-bg: #947962;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #947962;color:#fff}.bg-gradient-red-teal{--bslib-color-fg: #fff;--bslib-color-bg: #977e60;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #977e60;color:#fff}.bg-gradient-red-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #9f6a7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #9f6a7c;color:#fff}.bg-gradient-orange-blue{--bslib-color-fg: #fff;--bslib-color-bg: #a9642c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #a9642c;color:#fff}.bg-gradient-orange-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #c1526d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #c1526d;color:#fff}.bg-gradient-orange-purple{--bslib-color-fg: #fff;--bslib-color-bg: #c46659;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #c46659;color:#fff}.bg-gradient-orange-pink{--bslib-color-fg: #fff;--bslib-color-bg: #f56444;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #f56444;color:#fff}.bg-gradient-orange-red{--bslib-color-fg: #fff;--bslib-color-bg: #f46a24;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #f46a24;color:#fff}.bg-gradient-orange-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #f98a13;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #f98a13;color:#fff}.bg-gradient-orange-green{--bslib-color-fg: #fff;--bslib-color-bg: #a1974a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #a1974a;color:#fff}.bg-gradient-orange-teal{--bslib-color-fg: #fff;--bslib-color-bg: #a59c48;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #a59c48;color:#fff}.bg-gradient-orange-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #ad8864;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #ad8864;color:#fff}.bg-gradient-yellow-blue{--bslib-color-fg: #fff;--bslib-color-bg: #a3762b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #a3762b;color:#fff}.bg-gradient-yellow-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #bb646c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #bb646c;color:#fff}.bg-gradient-yellow-purple{--bslib-color-fg: #fff;--bslib-color-bg: #be7858;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #be7858;color:#fff}.bg-gradient-yellow-pink{--bslib-color-fg: #fff;--bslib-color-bg: #ef7643;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #ef7643;color:#fff}.bg-gradient-yellow-red{--bslib-color-fg: #fff;--bslib-color-bg: #ee7c23;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #ee7c23;color:#fff}.bg-gradient-yellow-orange{--bslib-color-fg: #fff;--bslib-color-bg: #f79013;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #f79013;color:#fff}.bg-gradient-yellow-green{--bslib-color-fg: #fff;--bslib-color-bg: #9ba949;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #9ba949;color:#fff}.bg-gradient-yellow-teal{--bslib-color-fg: #fff;--bslib-color-bg: #9fae47;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #9fae47;color:#fff}.bg-gradient-yellow-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #a79a62;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #a79a62;color:#fff}.bg-gradient-green-blue{--bslib-color-fg: #fff;--bslib-color-bg: #208a7e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #208a7e;color:#fff}.bg-gradient-green-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #3777be;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3777be;color:#fff}.bg-gradient-green-purple{--bslib-color-fg: #fff;--bslib-color-bg: #3b8bab;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #3b8bab;color:#fff}.bg-gradient-green-pink{--bslib-color-fg: #fff;--bslib-color-bg: #6b8a96;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #6b8a96;color:#fff}.bg-gradient-green-red{--bslib-color-fg: #fff;--bslib-color-bg: #6b8f76;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #6b8f76;color:#fff}.bg-gradient-green-orange{--bslib-color-fg: #fff;--bslib-color-bg: #74a366;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #74a366;color:#fff}.bg-gradient-green-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #70af65;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #70af65;color:#fff}.bg-gradient-green-teal{--bslib-color-fg: #fff;--bslib-color-bg: #1bc19a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #1bc19a;color:#fff}.bg-gradient-green-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #23aeb5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #23aeb5;color:#fff}.bg-gradient-teal-blue{--bslib-color-fg: #fff;--bslib-color-bg: #25917b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #25917b;color:#fff}.bg-gradient-teal-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #3c7fbb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3c7fbb;color:#fff}.bg-gradient-teal-purple{--bslib-color-fg: #fff;--bslib-color-bg: #4093a8;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #4093a8;color:#fff}.bg-gradient-teal-pink{--bslib-color-fg: #fff;--bslib-color-bg: #709193;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #709193;color:#fff}.bg-gradient-teal-red{--bslib-color-fg: #fff;--bslib-color-bg: #709773;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #709773;color:#fff}.bg-gradient-teal-orange{--bslib-color-fg: #fff;--bslib-color-bg: #78ab63;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #78ab63;color:#fff}.bg-gradient-teal-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #74b762;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #74b762;color:#fff}.bg-gradient-teal-green{--bslib-color-fg: #fff;--bslib-color-bg: #1dc499;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #1dc499;color:#fff}.bg-gradient-teal-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #28b5b2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #28b5b2;color:#fff}.bg-gradient-cyan-blue{--bslib-color-fg: #fff;--bslib-color-bg: #3174a3;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #3174a3;color:#fff}.bg-gradient-cyan-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #4862e4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #4862e4;color:#fff}.bg-gradient-cyan-purple{--bslib-color-fg: #fff;--bslib-color-bg: #4c76d1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #4c76d1;color:#fff}.bg-gradient-cyan-pink{--bslib-color-fg: #fff;--bslib-color-bg: #7c74bb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #7c74bb;color:#fff}.bg-gradient-cyan-red{--bslib-color-fg: #fff;--bslib-color-bg: #7c7a9b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #7c7a9b;color:#fff}.bg-gradient-cyan-orange{--bslib-color-fg: #fff;--bslib-color-bg: #848e8b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #848e8b;color:#fff}.bg-gradient-cyan-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #809a8b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #809a8b;color:#fff}.bg-gradient-cyan-green{--bslib-color-fg: #fff;--bslib-color-bg: #29a6c2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #29a6c2;color:#fff}.bg-gradient-cyan-teal{--bslib-color-fg: #fff;--bslib-color-bg: #2cacc0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #2cacc0;color:#fff}.bg-blue{--bslib-color-bg: #2c3e50;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-blue{--bslib-color-fg: #2c3e50;color:var(--bslib-color-fg)}.bg-indigo{--bslib-color-bg: #6610f2;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-indigo{--bslib-color-fg: #6610f2;color:var(--bslib-color-fg)}.bg-purple{--bslib-color-bg: #6f42c1;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-purple{--bslib-color-fg: #6f42c1;color:var(--bslib-color-fg)}.bg-pink{--bslib-color-bg: #e83e8c;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-pink{--bslib-color-fg: #e83e8c;color:var(--bslib-color-fg)}.bg-red{--bslib-color-bg: #e74c3c;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-red{--bslib-color-fg: #e74c3c;color:var(--bslib-color-fg)}.bg-orange{--bslib-color-bg: #fd7e14;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-orange{--bslib-color-fg: #fd7e14;color:var(--bslib-color-fg)}.bg-yellow{--bslib-color-bg: #f39c12;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-yellow{--bslib-color-fg: #f39c12;color:var(--bslib-color-fg)}.bg-green{--bslib-color-bg: #18bc9c;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-green{--bslib-color-fg: #18bc9c;color:var(--bslib-color-fg)}.bg-teal{--bslib-color-bg: #20c997;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-teal{--bslib-color-fg: #20c997;color:var(--bslib-color-fg)}.bg-cyan{--bslib-color-bg: #3498db;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-cyan{--bslib-color-fg: #3498db;color:var(--bslib-color-fg)}.text-default{--bslib-color-fg: #6c757d}.bg-default{--bslib-color-bg: #6c757d;--bslib-color-fg: #fff}.text-primary{--bslib-color-fg: #2c3e50}.bg-primary{--bslib-color-bg: #2c3e50;--bslib-color-fg: #fff}.text-secondary{--bslib-color-fg: #6c757d}.bg-secondary{--bslib-color-bg: #6c757d;--bslib-color-fg: #fff}.text-success{--bslib-color-fg: #18bc9c}.bg-success{--bslib-color-bg: #18bc9c;--bslib-color-fg: #fff}.text-info{--bslib-color-fg: #3498db}.bg-info{--bslib-color-bg: #3498db;--bslib-color-fg: #fff}.text-warning{--bslib-color-fg: #f39c12}.bg-warning{--bslib-color-bg: #f39c12;--bslib-color-fg: #fff}.text-danger{--bslib-color-fg: #e74c3c}.bg-danger{--bslib-color-bg: #e74c3c;--bslib-color-fg: #fff}.text-light{--bslib-color-fg: #ecf0f1}.bg-light{--bslib-color-bg: #ecf0f1;--bslib-color-fg: #000}.text-dark{--bslib-color-fg: #7b8a8b}.bg-dark{--bslib-color-bg: #7b8a8b;--bslib-color-fg: #fff}.bg-gradient-blue-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #432c91;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #432c91;color:#fff}.bg-gradient-blue-purple{--bslib-color-fg: #fff;--bslib-color-bg: #47407d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #47407d;color:#fff}.bg-gradient-blue-pink{--bslib-color-fg: #fff;--bslib-color-bg: #773e68;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #773e68;color:#fff}.bg-gradient-blue-red{--bslib-color-fg: #fff;--bslib-color-bg: #774448;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #774448;color:#fff}.bg-gradient-blue-orange{--bslib-color-fg: #fff;--bslib-color-bg: #805838;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #805838;color:#fff}.bg-gradient-blue-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #7c6437;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #7c6437;color:#fff}.bg-gradient-blue-green{--bslib-color-fg: #fff;--bslib-color-bg: #24706e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #24706e;color:#fff}.bg-gradient-blue-teal{--bslib-color-fg: #fff;--bslib-color-bg: #27766c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #27766c;color:#fff}.bg-gradient-blue-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #2f6288;background:linear-gradient(var(--bg-gradient-deg, 140deg), #2c3e50 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #2f6288;color:#fff}.bg-gradient-indigo-blue{--bslib-color-fg: #fff;--bslib-color-bg: #4f22b1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #4f22b1;color:#fff}.bg-gradient-indigo-purple{--bslib-color-fg: #fff;--bslib-color-bg: #6a24de;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #6a24de;color:#fff}.bg-gradient-indigo-pink{--bslib-color-fg: #fff;--bslib-color-bg: #9a22c9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #9a22c9;color:#fff}.bg-gradient-indigo-red{--bslib-color-fg: #fff;--bslib-color-bg: #9a28a9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #9a28a9;color:#fff}.bg-gradient-indigo-orange{--bslib-color-fg: #fff;--bslib-color-bg: #a23c99;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a23c99;color:#fff}.bg-gradient-indigo-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #9e4898;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #9e4898;color:#fff}.bg-gradient-indigo-green{--bslib-color-fg: #fff;--bslib-color-bg: #4755d0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #4755d0;color:#fff}.bg-gradient-indigo-teal{--bslib-color-fg: #fff;--bslib-color-bg: #4a5ace;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4a5ace;color:#fff}.bg-gradient-indigo-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #5246e9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #5246e9;color:#fff}.bg-gradient-purple-blue{--bslib-color-fg: #fff;--bslib-color-bg: #544094;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #544094;color:#fff}.bg-gradient-purple-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #6b2ed5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #6b2ed5;color:#fff}.bg-gradient-purple-pink{--bslib-color-fg: #fff;--bslib-color-bg: #9f40ac;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #9f40ac;color:#fff}.bg-gradient-purple-red{--bslib-color-fg: #fff;--bslib-color-bg: #9f468c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #9f468c;color:#fff}.bg-gradient-purple-orange{--bslib-color-fg: #fff;--bslib-color-bg: #a85a7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a85a7c;color:#fff}.bg-gradient-purple-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #a4667b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #a4667b;color:#fff}.bg-gradient-purple-green{--bslib-color-fg: #fff;--bslib-color-bg: #4c73b2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #4c73b2;color:#fff}.bg-gradient-purple-teal{--bslib-color-fg: #fff;--bslib-color-bg: #4f78b0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4f78b0;color:#fff}.bg-gradient-purple-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #5764cb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #5764cb;color:#fff}.bg-gradient-pink-blue{--bslib-color-fg: #fff;--bslib-color-bg: #9d3e74;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #9d3e74;color:#fff}.bg-gradient-pink-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #b42cb5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #b42cb5;color:#fff}.bg-gradient-pink-purple{--bslib-color-fg: #fff;--bslib-color-bg: #b840a1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #b840a1;color:#fff}.bg-gradient-pink-red{--bslib-color-fg: #fff;--bslib-color-bg: #e8446c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #e8446c;color:#fff}.bg-gradient-pink-orange{--bslib-color-fg: #fff;--bslib-color-bg: #f0585c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #f0585c;color:#fff}.bg-gradient-pink-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #ec645b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #ec645b;color:#fff}.bg-gradient-pink-green{--bslib-color-fg: #fff;--bslib-color-bg: #957092;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #957092;color:#fff}.bg-gradient-pink-teal{--bslib-color-fg: #fff;--bslib-color-bg: #987690;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #987690;color:#fff}.bg-gradient-pink-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #a062ac;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e83e8c var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #a062ac;color:#fff}.bg-gradient-red-blue{--bslib-color-fg: #fff;--bslib-color-bg: #9c4644;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #9c4644;color:#fff}.bg-gradient-red-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #b33485;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #b33485;color:#fff}.bg-gradient-red-purple{--bslib-color-fg: #fff;--bslib-color-bg: #b74871;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #b74871;color:#fff}.bg-gradient-red-pink{--bslib-color-fg: #fff;--bslib-color-bg: #e7465c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #e7465c;color:#fff}.bg-gradient-red-orange{--bslib-color-fg: #fff;--bslib-color-bg: #f0602c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #f0602c;color:#fff}.bg-gradient-red-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #ec6c2b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #ec6c2b;color:#fff}.bg-gradient-red-green{--bslib-color-fg: #fff;--bslib-color-bg: #947962;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #947962;color:#fff}.bg-gradient-red-teal{--bslib-color-fg: #fff;--bslib-color-bg: #977e60;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #977e60;color:#fff}.bg-gradient-red-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #9f6a7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #e74c3c var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #9f6a7c;color:#fff}.bg-gradient-orange-blue{--bslib-color-fg: #fff;--bslib-color-bg: #a9642c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #a9642c;color:#fff}.bg-gradient-orange-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #c1526d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #c1526d;color:#fff}.bg-gradient-orange-purple{--bslib-color-fg: #fff;--bslib-color-bg: #c46659;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #c46659;color:#fff}.bg-gradient-orange-pink{--bslib-color-fg: #fff;--bslib-color-bg: #f56444;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #f56444;color:#fff}.bg-gradient-orange-red{--bslib-color-fg: #fff;--bslib-color-bg: #f46a24;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #f46a24;color:#fff}.bg-gradient-orange-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #f98a13;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #f98a13;color:#fff}.bg-gradient-orange-green{--bslib-color-fg: #fff;--bslib-color-bg: #a1974a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #a1974a;color:#fff}.bg-gradient-orange-teal{--bslib-color-fg: #fff;--bslib-color-bg: #a59c48;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #a59c48;color:#fff}.bg-gradient-orange-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #ad8864;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #ad8864;color:#fff}.bg-gradient-yellow-blue{--bslib-color-fg: #fff;--bslib-color-bg: #a3762b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #a3762b;color:#fff}.bg-gradient-yellow-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #bb646c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #bb646c;color:#fff}.bg-gradient-yellow-purple{--bslib-color-fg: #fff;--bslib-color-bg: #be7858;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #be7858;color:#fff}.bg-gradient-yellow-pink{--bslib-color-fg: #fff;--bslib-color-bg: #ef7643;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #ef7643;color:#fff}.bg-gradient-yellow-red{--bslib-color-fg: #fff;--bslib-color-bg: #ee7c23;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #ee7c23;color:#fff}.bg-gradient-yellow-orange{--bslib-color-fg: #fff;--bslib-color-bg: #f79013;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #f79013;color:#fff}.bg-gradient-yellow-green{--bslib-color-fg: #fff;--bslib-color-bg: #9ba949;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #9ba949;color:#fff}.bg-gradient-yellow-teal{--bslib-color-fg: #fff;--bslib-color-bg: #9fae47;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #9fae47;color:#fff}.bg-gradient-yellow-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #a79a62;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f39c12 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #a79a62;color:#fff}.bg-gradient-green-blue{--bslib-color-fg: #fff;--bslib-color-bg: #208a7e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #208a7e;color:#fff}.bg-gradient-green-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #3777be;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3777be;color:#fff}.bg-gradient-green-purple{--bslib-color-fg: #fff;--bslib-color-bg: #3b8bab;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #3b8bab;color:#fff}.bg-gradient-green-pink{--bslib-color-fg: #fff;--bslib-color-bg: #6b8a96;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #6b8a96;color:#fff}.bg-gradient-green-red{--bslib-color-fg: #fff;--bslib-color-bg: #6b8f76;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #6b8f76;color:#fff}.bg-gradient-green-orange{--bslib-color-fg: #fff;--bslib-color-bg: #74a366;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #74a366;color:#fff}.bg-gradient-green-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #70af65;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #70af65;color:#fff}.bg-gradient-green-teal{--bslib-color-fg: #fff;--bslib-color-bg: #1bc19a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #1bc19a;color:#fff}.bg-gradient-green-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #23aeb5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #18bc9c var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #23aeb5;color:#fff}.bg-gradient-teal-blue{--bslib-color-fg: #fff;--bslib-color-bg: #25917b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #25917b;color:#fff}.bg-gradient-teal-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #3c7fbb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3c7fbb;color:#fff}.bg-gradient-teal-purple{--bslib-color-fg: #fff;--bslib-color-bg: #4093a8;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #4093a8;color:#fff}.bg-gradient-teal-pink{--bslib-color-fg: #fff;--bslib-color-bg: #709193;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #709193;color:#fff}.bg-gradient-teal-red{--bslib-color-fg: #fff;--bslib-color-bg: #709773;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #709773;color:#fff}.bg-gradient-teal-orange{--bslib-color-fg: #fff;--bslib-color-bg: #78ab63;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #78ab63;color:#fff}.bg-gradient-teal-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #74b762;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #74b762;color:#fff}.bg-gradient-teal-green{--bslib-color-fg: #fff;--bslib-color-bg: #1dc499;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #1dc499;color:#fff}.bg-gradient-teal-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #28b5b2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #3498db var(--bg-gradient-end, 180%)) #28b5b2;color:#fff}.bg-gradient-cyan-blue{--bslib-color-fg: #fff;--bslib-color-bg: #3174a3;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #2c3e50 var(--bg-gradient-end, 180%)) #3174a3;color:#fff}.bg-gradient-cyan-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #4862e4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #4862e4;color:#fff}.bg-gradient-cyan-purple{--bslib-color-fg: #fff;--bslib-color-bg: #4c76d1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #4c76d1;color:#fff}.bg-gradient-cyan-pink{--bslib-color-fg: #fff;--bslib-color-bg: #7c74bb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #e83e8c var(--bg-gradient-end, 180%)) #7c74bb;color:#fff}.bg-gradient-cyan-red{--bslib-color-fg: #fff;--bslib-color-bg: #7c7a9b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #e74c3c var(--bg-gradient-end, 180%)) #7c7a9b;color:#fff}.bg-gradient-cyan-orange{--bslib-color-fg: #fff;--bslib-color-bg: #848e8b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #848e8b;color:#fff}.bg-gradient-cyan-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #809a8b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #f39c12 var(--bg-gradient-end, 180%)) #809a8b;color:#fff}.bg-gradient-cyan-green{--bslib-color-fg: #fff;--bslib-color-bg: #29a6c2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #18bc9c var(--bg-gradient-end, 180%)) #29a6c2;color:#fff}.bg-gradient-cyan-teal{--bslib-color-fg: #fff;--bslib-color-bg: #2cacc0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #3498db var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #2cacc0;color:#fff}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0}.bslib-card{overflow:auto}.bslib-card .card-body+.card-body{padding-top:0}.bslib-card .card-body{overflow:auto}.bslib-card .card-body p{margin-top:0}.bslib-card .card-body p:last-child{margin-bottom:0}.bslib-card .card-body{max-height:var(--bslib-card-body-max-height, none)}.bslib-card[data-full-screen=true]>.card-body{max-height:var(--bslib-card-body-max-height-full-screen, none)}.bslib-card .card-header .form-group{margin-bottom:0}.bslib-card .card-header .selectize-control{margin-bottom:0}.bslib-card .card-header .selectize-control .item{margin-right:1.15rem}.bslib-card .card-footer{margin-top:auto}.bslib-card .bslib-navs-card-title{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}.bslib-card .bslib-navs-card-title .nav{margin-left:auto}.bslib-card .bslib-sidebar-layout:not([data-bslib-sidebar-border=true]){border:none}.bslib-card .bslib-sidebar-layout:not([data-bslib-sidebar-border-radius=true]){border-top-left-radius:0;border-top-right-radius:0}[data-full-screen=true]{position:fixed;inset:3.5rem 1rem 1rem;height:auto !important;max-height:none !important;width:auto !important;z-index:1070}.bslib-full-screen-enter{display:none;position:absolute;bottom:var(--bslib-full-screen-enter-bottom, 0.2rem);right:var(--bslib-full-screen-enter-right, 0);top:var(--bslib-full-screen-enter-top);left:var(--bslib-full-screen-enter-left);color:var(--bslib-color-fg, var(--bs-card-color));background-color:var(--bslib-color-bg, var(--bs-card-bg, var(--bs-body-bg)));border:var(--bs-card-border-width) solid var(--bslib-color-fg, var(--bs-card-border-color));box-shadow:0 2px 4px rgba(0,0,0,.15);margin:.2rem .4rem;padding:.55rem !important;font-size:.8rem;cursor:pointer;opacity:.7;z-index:1070}.bslib-full-screen-enter:hover{opacity:1}.card[data-full-screen=false]:hover>*>.bslib-full-screen-enter{display:block}.bslib-has-full-screen .card:hover>*>.bslib-full-screen-enter{display:none}@media(max-width: 575.98px){.bslib-full-screen-enter{display:none !important}}.bslib-full-screen-exit{position:relative;top:1.35rem;font-size:.9rem;cursor:pointer;text-decoration:none;display:flex;float:right;margin-right:2.15rem;align-items:center;color:rgba(var(--bs-body-bg-rgb), 0.8)}.bslib-full-screen-exit:hover{color:rgba(var(--bs-body-bg-rgb), 1)}.bslib-full-screen-exit svg{margin-left:.5rem;font-size:1.5rem}#bslib-full-screen-overlay{position:fixed;inset:0;background-color:rgba(var(--bs-body-color-rgb), 0.6);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:1069;animation:bslib-full-screen-overlay-enter 400ms cubic-bezier(0.6, 0.02, 0.65, 1) forwards}@keyframes bslib-full-screen-overlay-enter{0%{opacity:0}100%{opacity:1}}.bslib-grid{display:grid !important;gap:var(--bslib-spacer, 1rem);height:var(--bslib-grid-height)}.bslib-grid.grid{grid-template-columns:repeat(var(--bs-columns, 12), minmax(0, 1fr));grid-template-rows:unset;grid-auto-rows:var(--bslib-grid--row-heights);--bslib-grid--row-heights--xs: unset;--bslib-grid--row-heights--sm: unset;--bslib-grid--row-heights--md: unset;--bslib-grid--row-heights--lg: unset;--bslib-grid--row-heights--xl: unset;--bslib-grid--row-heights--xxl: unset}.bslib-grid.grid.bslib-grid--row-heights--xs{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xs)}@media(min-width: 576px){.bslib-grid.grid.bslib-grid--row-heights--sm{--bslib-grid--row-heights: var(--bslib-grid--row-heights--sm)}}@media(min-width: 768px){.bslib-grid.grid.bslib-grid--row-heights--md{--bslib-grid--row-heights: var(--bslib-grid--row-heights--md)}}@media(min-width: 992px){.bslib-grid.grid.bslib-grid--row-heights--lg{--bslib-grid--row-heights: var(--bslib-grid--row-heights--lg)}}@media(min-width: 1200px){.bslib-grid.grid.bslib-grid--row-heights--xl{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xl)}}@media(min-width: 1400px){.bslib-grid.grid.bslib-grid--row-heights--xxl{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xxl)}}.bslib-grid>*>.shiny-input-container{width:100%}.bslib-grid-item{grid-column:auto/span 1}@media(max-width: 767.98px){.bslib-grid-item{grid-column:1/-1}}@media(max-width: 575.98px){.bslib-grid{grid-template-columns:1fr !important;height:var(--bslib-grid-height-mobile)}.bslib-grid.grid{height:unset !important;grid-auto-rows:var(--bslib-grid--row-heights--xs, auto)}}@media(min-width: 576px){.nav:not(.nav-hidden){display:flex !important;display:-webkit-flex !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column){float:none !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column)>.bslib-nav-spacer{margin-left:auto !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column)>.form-inline{margin-top:auto;margin-bottom:auto}.nav:not(.nav-hidden).nav-stacked{flex-direction:column;-webkit-flex-direction:column;height:100%}.nav:not(.nav-hidden).nav-stacked>.bslib-nav-spacer{margin-top:auto !important}}.accordion .accordion-header{font-size:calc(1.29rem + 0.48vw);margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color);margin-bottom:0}@media(min-width: 1200px){.accordion .accordion-header{font-size:1.65rem}}.accordion .accordion-icon:not(:empty){margin-right:.75rem;display:flex}.accordion .accordion-button:not(.collapsed){box-shadow:none}.accordion .accordion-button:not(.collapsed):focus{box-shadow:var(--bs-accordion-btn-focus-box-shadow)}html{height:100%}.bslib-page-fill{width:100%;height:100%;margin:0;padding:var(--bslib-spacer, 1rem);gap:var(--bslib-spacer, 1rem)}@media(max-width: 575.98px){.bslib-page-fill{height:var(--bslib-page-fill-mobile-height, auto)}}:root{--bslib-value-box-shadow: none;--bslib-value-box-border-width-auto-yes: var(--bslib-value-box-border-width-baseline);--bslib-value-box-border-width-auto-no: 0;--bslib-value-box-border-width-baseline: 1px}.bslib-value-box{border-width:var(--bslib-value-box-border-width-auto-no, var(--bslib-value-box-border-width-baseline));container-name:bslib-value-box;container-type:inline-size}.bslib-value-box.card{box-shadow:var(--bslib-value-box-shadow)}.bslib-value-box.border-auto{border-width:var(--bslib-value-box-border-width-auto-yes, var(--bslib-value-box-border-width-baseline))}.bslib-value-box.default{--bslib-value-box-bg-default: var(--bs-card-bg, #fff);--bslib-value-box-border-color-default: var(--bs-card-border-color, rgba(0, 0, 0, 0.175));color:var(--bslib-value-box-color);background-color:var(--bslib-value-box-bg, var(--bslib-value-box-bg-default));border-color:var(--bslib-value-box-border-color, var(--bslib-value-box-border-color-default))}.bslib-value-box .value-box-grid{display:grid;grid-template-areas:"left right";align-items:center;overflow:hidden}.bslib-value-box .value-box-showcase{height:100%;max-height:var(---bslib-value-box-showcase-max-h, 100%)}.bslib-value-box .value-box-showcase,.bslib-value-box .value-box-showcase>.html-fill-item{width:100%}.bslib-value-box[data-full-screen=true] .value-box-showcase{max-height:var(---bslib-value-box-showcase-max-h-fs, 100%)}@media screen and (min-width: 575.98px){@container bslib-value-box (max-width: 300px){.bslib-value-box:not(.showcase-bottom) .value-box-grid{grid-template-columns:1fr !important;grid-template-rows:auto auto;grid-template-areas:"top" "bottom"}.bslib-value-box:not(.showcase-bottom) .value-box-grid .value-box-showcase{grid-area:top !important}.bslib-value-box:not(.showcase-bottom) .value-box-grid .value-box-area{grid-area:bottom !important;justify-content:end}}}.bslib-value-box .value-box-area{justify-content:center;padding:1.5rem 1rem;font-size:.9rem;font-weight:500}.bslib-value-box .value-box-area *{margin-bottom:0;margin-top:0}.bslib-value-box .value-box-title{font-size:1rem;margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.bslib-value-box .value-box-title:empty::after{content:" "}.bslib-value-box .value-box-value{font-size:calc(1.29rem + 0.48vw);margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}@media(min-width: 1200px){.bslib-value-box .value-box-value{font-size:1.65rem}}.bslib-value-box .value-box-value:empty::after{content:" "}.bslib-value-box .value-box-showcase{align-items:center;justify-content:center;margin-top:auto;margin-bottom:auto;padding:1rem}.bslib-value-box .value-box-showcase .bi,.bslib-value-box .value-box-showcase .fa,.bslib-value-box .value-box-showcase .fab,.bslib-value-box .value-box-showcase .fas,.bslib-value-box .value-box-showcase .far{opacity:.85;min-width:50px;max-width:125%}.bslib-value-box .value-box-showcase .bi,.bslib-value-box .value-box-showcase .fa,.bslib-value-box .value-box-showcase .fab,.bslib-value-box .value-box-showcase .fas,.bslib-value-box .value-box-showcase .far{font-size:4rem}.bslib-value-box.showcase-top-right .value-box-grid{grid-template-columns:1fr var(---bslib-value-box-showcase-w, 50%)}.bslib-value-box.showcase-top-right .value-box-grid .value-box-showcase{grid-area:right;margin-left:auto;align-self:start;align-items:end;padding-left:0;padding-bottom:0}.bslib-value-box.showcase-top-right .value-box-grid .value-box-area{grid-area:left;align-self:end}.bslib-value-box.showcase-top-right[data-full-screen=true] .value-box-grid{grid-template-columns:auto var(---bslib-value-box-showcase-w-fs, 1fr)}.bslib-value-box.showcase-top-right[data-full-screen=true] .value-box-grid>div{align-self:center}.bslib-value-box.showcase-top-right:not([data-full-screen=true]) .value-box-showcase{margin-top:0}@container bslib-value-box (max-width: 300px){.bslib-value-box.showcase-top-right:not([data-full-screen=true]) .value-box-grid .value-box-showcase{padding-left:1rem}}.bslib-value-box.showcase-left-center .value-box-grid{grid-template-columns:var(---bslib-value-box-showcase-w, 30%) auto}.bslib-value-box.showcase-left-center[data-full-screen=true] .value-box-grid{grid-template-columns:var(---bslib-value-box-showcase-w-fs, 1fr) auto}.bslib-value-box.showcase-left-center:not([data-fill-screen=true]) .value-box-grid .value-box-showcase{grid-area:left}.bslib-value-box.showcase-left-center:not([data-fill-screen=true]) .value-box-grid .value-box-area{grid-area:right}.bslib-value-box.showcase-bottom .value-box-grid{grid-template-columns:1fr;grid-template-rows:1fr var(---bslib-value-box-showcase-h, auto);grid-template-areas:"top" "bottom";overflow:hidden}.bslib-value-box.showcase-bottom .value-box-grid .value-box-showcase{grid-area:bottom;padding:0;margin:0}.bslib-value-box.showcase-bottom .value-box-grid .value-box-area{grid-area:top}.bslib-value-box.showcase-bottom[data-full-screen=true] .value-box-grid{grid-template-rows:1fr var(---bslib-value-box-showcase-h-fs, 2fr)}.bslib-value-box.showcase-bottom[data-full-screen=true] .value-box-grid .value-box-showcase{padding:1rem}[data-bs-theme=dark] .bslib-value-box{--bslib-value-box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 50%)}.navbar+.container-fluid:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-sm:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-md:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-lg:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-xl:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-xxl:has(>.tab-content>.tab-pane.active.html-fill-container){padding-left:0;padding-right:0}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container{padding:var(--bslib-spacer, 1rem);gap:var(--bslib-spacer, 1rem)}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child){padding:0}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]){border-left:none;border-right:none;border-bottom:none}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]){border-radius:0}.navbar+div>.bslib-sidebar-layout{border-top:var(--bslib-sidebar-border)}.bslib-sidebar-layout{--bslib-sidebar-transition-duration: 500ms;--bslib-sidebar-transition-easing-x: cubic-bezier(0.8, 0.78, 0.22, 1.07);--bslib-sidebar-border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0, 0, 0, 0.175));--bslib-sidebar-border-radius: var(--bs-border-radius);--bslib-sidebar-vert-border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0, 0, 0, 0.175));--bslib-sidebar-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.05);--bslib-sidebar-fg: var(--bs-emphasis-color, black);--bslib-sidebar-main-fg: var(--bs-card-color, var(--bs-body-color));--bslib-sidebar-main-bg: var(--bs-card-bg, var(--bs-body-bg));--bslib-sidebar-toggle-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.1);--bslib-sidebar-padding: calc(var(--bslib-spacer) * 1.5);--bslib-sidebar-icon-size: var(--bslib-spacer, 1rem);--bslib-sidebar-icon-button-size: calc(var(--bslib-sidebar-icon-size, 1rem) * 2);--bslib-sidebar-padding-icon: calc(var(--bslib-sidebar-icon-button-size, 2rem) * 1.5);--bslib-collapse-toggle-border-radius: var(--bs-border-radius, 0.25rem);--bslib-collapse-toggle-transform: 0deg;--bslib-sidebar-toggle-transition-easing: cubic-bezier(1, 0, 0, 1);--bslib-collapse-toggle-right-transform: 180deg;--bslib-sidebar-column-main: minmax(0, 1fr);display:grid !important;grid-template-columns:min(100% - var(--bslib-sidebar-icon-size),var(--bslib-sidebar-width, 250px)) var(--bslib-sidebar-column-main);position:relative;transition:grid-template-columns ease-in-out var(--bslib-sidebar-transition-duration);border:var(--bslib-sidebar-border);border-radius:var(--bslib-sidebar-border-radius)}@media(prefers-reduced-motion: reduce){.bslib-sidebar-layout{transition:none}}.bslib-sidebar-layout[data-bslib-sidebar-border=false]{border:none}.bslib-sidebar-layout[data-bslib-sidebar-border-radius=false]{border-radius:initial}.bslib-sidebar-layout>.main,.bslib-sidebar-layout>.sidebar{grid-row:1/2;border-radius:inherit;overflow:auto}.bslib-sidebar-layout>.main{grid-column:2/3;border-top-left-radius:0;border-bottom-left-radius:0;padding:var(--bslib-sidebar-padding);transition:padding var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration);color:var(--bslib-sidebar-main-fg);background-color:var(--bslib-sidebar-main-bg)}.bslib-sidebar-layout>.sidebar{grid-column:1/2;width:100%;height:100%;border-right:var(--bslib-sidebar-vert-border);border-top-right-radius:0;border-bottom-right-radius:0;color:var(--bslib-sidebar-fg);background-color:var(--bslib-sidebar-bg);backdrop-filter:blur(5px)}.bslib-sidebar-layout>.sidebar>.sidebar-content{display:flex;flex-direction:column;gap:var(--bslib-spacer, 1rem);padding:var(--bslib-sidebar-padding);padding-top:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout>.sidebar>.sidebar-content>:last-child:not(.sidebar-title){margin-bottom:0}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion{margin-left:calc(-1*var(--bslib-sidebar-padding));margin-right:calc(-1*var(--bslib-sidebar-padding))}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:last-child{margin-bottom:calc(-1*var(--bslib-sidebar-padding))}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:last-child){margin-bottom:1rem}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion .accordion-body{display:flex;flex-direction:column}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:first-child) .accordion-item:first-child{border-top:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:last-child) .accordion-item:last-child{border-bottom:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.bslib-sidebar-layout>.sidebar>.sidebar-content.has-accordion>.sidebar-title{border-bottom:none;padding-bottom:0}.bslib-sidebar-layout>.sidebar .shiny-input-container{width:100%}.bslib-sidebar-layout[data-bslib-sidebar-open=always]>.sidebar>.sidebar-content{padding-top:var(--bslib-sidebar-padding)}.bslib-sidebar-layout>.collapse-toggle{grid-row:1/2;grid-column:1/2;display:inline-flex;align-items:center;position:absolute;right:calc(var(--bslib-sidebar-icon-size));top:calc(var(--bslib-sidebar-icon-size, 1rem)/2);border:none;border-radius:var(--bslib-collapse-toggle-border-radius);height:var(--bslib-sidebar-icon-button-size, 2rem);width:var(--bslib-sidebar-icon-button-size, 2rem);display:flex;align-items:center;justify-content:center;padding:0;color:var(--bslib-sidebar-fg);background-color:unset;transition:color var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),top var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),right var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),left var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout>.collapse-toggle:hover{background-color:var(--bslib-sidebar-toggle-bg)}.bslib-sidebar-layout>.collapse-toggle>.collapse-icon{opacity:.8;width:var(--bslib-sidebar-icon-size);height:var(--bslib-sidebar-icon-size);transform:rotateY(var(--bslib-collapse-toggle-transform));transition:transform var(--bslib-sidebar-toggle-transition-easing) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout>.collapse-toggle:hover>.collapse-icon{opacity:1}.bslib-sidebar-layout .sidebar-title{font-size:1.25rem;line-height:1.25;margin-top:0;margin-bottom:1rem;padding-bottom:1rem;border-bottom:var(--bslib-sidebar-border)}.bslib-sidebar-layout.sidebar-right{grid-template-columns:var(--bslib-sidebar-column-main) min(100% - var(--bslib-sidebar-icon-size),var(--bslib-sidebar-width, 250px))}.bslib-sidebar-layout.sidebar-right>.main{grid-column:1/2;border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:inherit;border-bottom-left-radius:inherit}.bslib-sidebar-layout.sidebar-right>.sidebar{grid-column:2/3;border-right:none;border-left:var(--bslib-sidebar-vert-border);border-top-left-radius:0;border-bottom-left-radius:0}.bslib-sidebar-layout.sidebar-right>.collapse-toggle{grid-column:2/3;left:var(--bslib-sidebar-icon-size);right:unset;border:var(--bslib-collapse-toggle-border)}.bslib-sidebar-layout.sidebar-right>.collapse-toggle>.collapse-icon{transform:rotateY(var(--bslib-collapse-toggle-right-transform))}.bslib-sidebar-layout.sidebar-collapsed{--bslib-collapse-toggle-transform: 180deg;--bslib-collapse-toggle-right-transform: 0deg;--bslib-sidebar-vert-border: none;grid-template-columns:0 minmax(0, 1fr)}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right{grid-template-columns:minmax(0, 1fr) 0}.bslib-sidebar-layout.sidebar-collapsed:not(.transitioning)>.sidebar>*{display:none}.bslib-sidebar-layout.sidebar-collapsed>.main{border-radius:inherit}.bslib-sidebar-layout.sidebar-collapsed:not(.sidebar-right)>.main{padding-left:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.main{padding-right:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout.sidebar-collapsed>.collapse-toggle{color:var(--bslib-sidebar-main-fg);top:calc(var(--bslib-sidebar-overlap-counter, 0)*(var(--bslib-sidebar-icon-size) + var(--bslib-sidebar-padding)) + var(--bslib-sidebar-icon-size, 1rem)/2);right:calc(-2.5*var(--bslib-sidebar-icon-size) - var(--bs-card-border-width, 1px))}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.collapse-toggle{left:calc(-2.5*var(--bslib-sidebar-icon-size) - var(--bs-card-border-width, 1px));right:unset}@media(min-width: 576px){.bslib-sidebar-layout.transitioning>.sidebar>.sidebar-content{display:none}}@media(max-width: 575.98px){.bslib-sidebar-layout[data-bslib-sidebar-open=desktop]{--bslib-sidebar-js-init-collapsed: true}.bslib-sidebar-layout>.sidebar,.bslib-sidebar-layout.sidebar-right>.sidebar{border:none}.bslib-sidebar-layout>.main,.bslib-sidebar-layout.sidebar-right>.main{grid-column:1/3}.bslib-sidebar-layout[data-bslib-sidebar-open=always]{display:block !important}.bslib-sidebar-layout[data-bslib-sidebar-open=always]>.sidebar{max-height:var(--bslib-sidebar-max-height-mobile);overflow-y:auto;border-top:var(--bslib-sidebar-vert-border)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]){grid-template-columns:100% 0}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-collapsed)>.sidebar{z-index:1}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-collapsed)>.collapse-toggle{z-index:1}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-right{grid-template-columns:0 100%}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed{grid-template-columns:0 100%}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed.sidebar-right{grid-template-columns:100% 0}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-right)>.main{padding-left:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-right>.main{padding-right:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always])>.main{opacity:0;transition:opacity var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed>.main{opacity:1}}:root{--bslib-page-sidebar-title-bg: #ececec;--bslib-page-sidebar-title-color: #000}.bslib-page-title{background-color:var(--bslib-page-sidebar-title-bg);color:var(--bslib-page-sidebar-title-color);font-size:1.25rem;font-weight:300;padding:var(--bslib-spacer, 1rem);padding-left:1.5rem;margin-bottom:0;border-bottom:1px solid #dee2e6}.html-fill-container{display:flex;flex-direction:column;min-height:0;min-width:0}.html-fill-container>.html-fill-item{flex:1 1 auto;min-height:0;min-width:0}.html-fill-container>:not(.html-fill-item){flex:0 0 auto}.quarto-container{min-height:calc(100vh - 132px)}body.hypothesis-enabled #quarto-header{margin-right:16px}footer.footer .nav-footer,#quarto-header>nav{padding-left:1em;padding-right:1em}footer.footer div.nav-footer p:first-child{margin-top:0}footer.footer div.nav-footer p:last-child{margin-bottom:0}#quarto-content>*{padding-top:14px}#quarto-content>#quarto-sidebar-glass{padding-top:0px}@media(max-width: 991.98px){#quarto-content>*{padding-top:0}#quarto-content .subtitle{padding-top:14px}#quarto-content section:first-of-type h2:first-of-type,#quarto-content section:first-of-type .h2:first-of-type{margin-top:1rem}}.headroom-target,header.headroom{will-change:transform;transition:position 200ms linear;transition:all 200ms linear}header.headroom--pinned{transform:translateY(0%)}header.headroom--unpinned{transform:translateY(-100%)}.navbar-container{width:100%}.navbar-brand{overflow:hidden;text-overflow:ellipsis}.navbar-brand-container{max-width:calc(100% - 115px);min-width:0;display:flex;align-items:center}@media(min-width: 992px){.navbar-brand-container{margin-right:1em}}.navbar-brand.navbar-brand-logo{margin-right:4px;display:inline-flex}.navbar-toggler{flex-basis:content;flex-shrink:0}.navbar .navbar-brand-container{order:2}.navbar .navbar-toggler{order:1}.navbar .navbar-container>.navbar-nav{order:20}.navbar .navbar-container>.navbar-brand-container{margin-left:0 !important;margin-right:0 !important}.navbar .navbar-collapse{order:20}.navbar #quarto-search{order:4;margin-left:auto}.navbar .navbar-toggler{margin-right:.5em}.navbar-collapse .quarto-navbar-tools{margin-left:.5em}.navbar-logo{max-height:24px;width:auto;padding-right:4px}nav .nav-item:not(.compact){padding-top:1px}nav .nav-link i,nav .dropdown-item i{padding-right:1px}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.6rem;padding-right:.6rem}nav .nav-item.compact .nav-link{padding-left:.5rem;padding-right:.5rem;font-size:1.1rem}.navbar .quarto-navbar-tools{order:3}.navbar .quarto-navbar-tools div.dropdown{display:inline-block}.navbar .quarto-navbar-tools .quarto-navigation-tool{color:#222}.navbar .quarto-navbar-tools .quarto-navigation-tool:hover{color:#5e7ca1}.navbar-nav .dropdown-menu{min-width:220px;font-size:.9rem}.navbar .navbar-nav .nav-link.dropdown-toggle::after{opacity:.75;vertical-align:.175em}.navbar ul.dropdown-menu{padding-top:0;padding-bottom:0}.navbar .dropdown-header{text-transform:uppercase;font-size:.8rem;padding:0 .5rem}.navbar .dropdown-item{padding:.4rem .5rem}.navbar .dropdown-item>i.bi{margin-left:.1rem;margin-right:.25em}.sidebar #quarto-search{margin-top:-1px}.sidebar #quarto-search svg.aa-SubmitIcon{width:16px;height:16px}.sidebar-navigation a{color:inherit}.sidebar-title{margin-top:.25rem;padding-bottom:.5rem;font-size:1.3rem;line-height:1.6rem;visibility:visible}.sidebar-title>a{font-size:inherit;text-decoration:none}.sidebar-title .sidebar-tools-main{margin-top:-6px}@media(max-width: 991.98px){#quarto-sidebar div.sidebar-header{padding-top:.2em}}.sidebar-header-stacked .sidebar-title{margin-top:.6rem}.sidebar-logo{max-width:90%;padding-bottom:.5rem}.sidebar-logo-link{text-decoration:none}.sidebar-navigation li a{text-decoration:none}.sidebar-navigation .quarto-navigation-tool{opacity:.7;font-size:.875rem}#quarto-sidebar>nav>.sidebar-tools-main{margin-left:14px}.sidebar-tools-main{display:inline-flex;margin-left:0px;order:2}.sidebar-tools-main:not(.tools-wide){vertical-align:middle}.sidebar-navigation .quarto-navigation-tool.dropdown-toggle::after{display:none}.sidebar.sidebar-navigation>*{padding-top:1em}.sidebar-item{margin-bottom:.2em;line-height:1rem;margin-top:.4rem}.sidebar-section{padding-left:.5em;padding-bottom:.2em}.sidebar-item .sidebar-item-container{display:flex;justify-content:space-between;cursor:pointer}.sidebar-item-toggle:hover{cursor:pointer}.sidebar-item .sidebar-item-toggle .bi{font-size:.7rem;text-align:center}.sidebar-item .sidebar-item-toggle .bi-chevron-right::before{transition:transform 200ms ease}.sidebar-item .sidebar-item-toggle[aria-expanded=false] .bi-chevron-right::before{transform:none}.sidebar-item .sidebar-item-toggle[aria-expanded=true] .bi-chevron-right::before{transform:rotate(90deg)}.sidebar-item-text{width:100%}.sidebar-navigation .sidebar-divider{margin-left:0;margin-right:0;margin-top:.5rem;margin-bottom:.5rem}@media(max-width: 991.98px){.quarto-secondary-nav{display:block}.quarto-secondary-nav button.quarto-search-button{padding-right:0em;padding-left:2em}.quarto-secondary-nav button.quarto-btn-toggle{margin-left:-0.75rem;margin-right:.15rem}.quarto-secondary-nav nav.quarto-title-breadcrumbs{display:none}.quarto-secondary-nav nav.quarto-page-breadcrumbs{display:flex;align-items:center;padding-right:1em;margin-left:-0.25em}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{text-decoration:none}.quarto-secondary-nav nav.quarto-page-breadcrumbs ol.breadcrumb{margin-bottom:0}}@media(min-width: 992px){.quarto-secondary-nav{display:none}}.quarto-title-breadcrumbs .breadcrumb{margin-bottom:.5em;font-size:.9rem}.quarto-title-breadcrumbs .breadcrumb li:last-of-type a{color:#6c757d}.quarto-secondary-nav .quarto-btn-toggle{color:#222}.quarto-secondary-nav[aria-expanded=false] .quarto-btn-toggle .bi-chevron-right::before{transform:none}.quarto-secondary-nav[aria-expanded=true] .quarto-btn-toggle .bi-chevron-right::before{transform:rotate(90deg)}.quarto-secondary-nav .quarto-btn-toggle .bi-chevron-right::before{transition:transform 200ms ease}.quarto-secondary-nav{cursor:pointer}.no-decor{text-decoration:none}.quarto-secondary-nav-title{margin-top:.3em;color:#222;padding-top:4px}.quarto-secondary-nav nav.quarto-page-breadcrumbs{color:#222}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{color:#222}.quarto-secondary-nav nav.quarto-page-breadcrumbs a:hover{color:rgba(68,89,116,.8)}.quarto-secondary-nav nav.quarto-page-breadcrumbs .breadcrumb-item::before{color:#555}.breadcrumb-item{line-height:1.2rem}div.sidebar-item-container{color:#222}div.sidebar-item-container:hover,div.sidebar-item-container:focus{color:rgba(68,89,116,.8)}div.sidebar-item-container.disabled{color:rgba(34,34,34,.75)}div.sidebar-item-container .active,div.sidebar-item-container .show>.nav-link,div.sidebar-item-container .sidebar-link>code{color:#445974}div.sidebar.sidebar-navigation.rollup.quarto-sidebar-toggle-contents,nav.sidebar.sidebar-navigation:not(.rollup){background-color:#fff}@media(max-width: 991.98px){.sidebar-navigation .sidebar-item a,.nav-page .nav-page-text,.sidebar-navigation{font-size:1rem}.sidebar-navigation ul.sidebar-section.depth1 .sidebar-section-item{font-size:1.1rem}.sidebar-logo{display:none}.sidebar.sidebar-navigation{position:static;border-bottom:1px solid #dee2e6}.sidebar.sidebar-navigation.collapsing{position:fixed;z-index:1000}.sidebar.sidebar-navigation.show{position:fixed;z-index:1000}.sidebar.sidebar-navigation{min-height:100%}nav.quarto-secondary-nav{background-color:#fff;border-bottom:1px solid #dee2e6}.quarto-banner nav.quarto-secondary-nav{background-color:#ececec;color:#222;border-top:1px solid #dee2e6}.sidebar .sidebar-footer{visibility:visible;padding-top:1rem;position:inherit}.sidebar-tools-collapse{display:block}}#quarto-sidebar{transition:width .15s ease-in}#quarto-sidebar>*{padding-right:1em}@media(max-width: 991.98px){#quarto-sidebar .sidebar-menu-container{white-space:nowrap;min-width:225px}#quarto-sidebar.show{transition:width .15s ease-out}}@media(min-width: 992px){#quarto-sidebar{display:flex;flex-direction:column}.nav-page .nav-page-text,.sidebar-navigation .sidebar-section .sidebar-item{font-size:.875rem}.sidebar-navigation .sidebar-item{font-size:.925rem}.sidebar.sidebar-navigation{display:block;position:sticky}.sidebar-search{width:100%}.sidebar .sidebar-footer{visibility:visible}}@media(min-width: 992px){#quarto-sidebar-glass{display:none}}@media(max-width: 991.98px){#quarto-sidebar-glass{position:fixed;top:0;bottom:0;left:0;right:0;background-color:rgba(255,255,255,0);transition:background-color .15s ease-in;z-index:-1}#quarto-sidebar-glass.collapsing{z-index:1000}#quarto-sidebar-glass.show{transition:background-color .15s ease-out;background-color:rgba(102,102,102,.4);z-index:1000}}.sidebar .sidebar-footer{padding:.5rem 1rem;align-self:flex-end;color:#6c757d;width:100%}.quarto-page-breadcrumbs .breadcrumb-item+.breadcrumb-item,.quarto-page-breadcrumbs .breadcrumb-item{padding-right:.33em;padding-left:0}.quarto-page-breadcrumbs .breadcrumb-item::before{padding-right:.33em}.quarto-sidebar-footer{font-size:.875em}.sidebar-section .bi-chevron-right{vertical-align:middle}.sidebar-section .bi-chevron-right::before{font-size:.9em}.notransition{-webkit-transition:none !important;-moz-transition:none !important;-o-transition:none !important;transition:none !important}.btn:focus:not(:focus-visible){box-shadow:none}.page-navigation{display:flex;justify-content:space-between}.nav-page{padding-bottom:.75em}.nav-page .bi{font-size:1.8rem;vertical-align:middle}.nav-page .nav-page-text{padding-left:.25em;padding-right:.25em}.nav-page a{color:#6c757d;text-decoration:none;display:flex;align-items:center}.nav-page a:hover{color:#4b6381}.nav-footer .toc-actions{padding-bottom:.5em;padding-top:.5em}.nav-footer .toc-actions a,.nav-footer .toc-actions a:hover{text-decoration:none}.nav-footer .toc-actions ul{display:flex;list-style:none}.nav-footer .toc-actions ul :first-child{margin-left:auto}.nav-footer .toc-actions ul :last-child{margin-right:auto}.nav-footer .toc-actions ul li{padding-right:1.5em}.nav-footer .toc-actions ul li i.bi{padding-right:.4em}.nav-footer .toc-actions ul li:last-of-type{padding-right:0}.nav-footer{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-items:baseline;text-align:center;padding-top:.5rem;padding-bottom:.5rem;background-color:#fff}body.nav-fixed{padding-top:82px}.nav-footer-contents{color:#6c757d;margin-top:.25rem}.nav-footer{min-height:3.5em;color:#757575}.nav-footer a{color:#757575}.nav-footer .nav-footer-left{font-size:.825em}.nav-footer .nav-footer-center{font-size:.825em}.nav-footer .nav-footer-right{font-size:.825em}.nav-footer-left .footer-items,.nav-footer-center .footer-items,.nav-footer-right .footer-items{display:inline-flex;padding-top:.3em;padding-bottom:.3em;margin-bottom:0em}.nav-footer-left .footer-items .nav-link,.nav-footer-center .footer-items .nav-link,.nav-footer-right .footer-items .nav-link{padding-left:.6em;padding-right:.6em}@media(min-width: 768px){.nav-footer-left{flex:1 1 0px;text-align:left}}@media(max-width: 575.98px){.nav-footer-left{margin-bottom:1em;flex:100%}}@media(min-width: 768px){.nav-footer-right{flex:1 1 0px;text-align:right}}@media(max-width: 575.98px){.nav-footer-right{margin-bottom:1em;flex:100%}}.nav-footer-center{text-align:center;min-height:3em}@media(min-width: 768px){.nav-footer-center{flex:1 1 0px}}.nav-footer-center .footer-items{justify-content:center}@media(max-width: 767.98px){.nav-footer-center{margin-bottom:1em;flex:100%}}@media(max-width: 767.98px){.nav-footer-center{margin-top:3em;order:10}}.navbar .quarto-reader-toggle.reader .quarto-reader-toggle-btn{background-color:#222;border-radius:3px}@media(max-width: 991.98px){.quarto-reader-toggle{display:none}}.quarto-reader-toggle.reader.quarto-navigation-tool .quarto-reader-toggle-btn{background-color:#222;border-radius:3px}.quarto-reader-toggle .quarto-reader-toggle-btn{display:inline-flex;padding-left:.2em;padding-right:.2em;margin-left:-0.2em;margin-right:-0.2em;text-align:center}.navbar .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}#quarto-back-to-top{display:none;position:fixed;bottom:50px;background-color:#fff;border-radius:.25rem;box-shadow:0 .2rem .5rem #6c757d,0 0 .05rem #6c757d;color:#6c757d;text-decoration:none;font-size:.9em;text-align:center;left:50%;padding:.4rem .8rem;transform:translate(-50%, 0)}#quarto-announcement{padding:.5em;display:flex;justify-content:space-between;margin-bottom:0;font-size:.9em}#quarto-announcement .quarto-announcement-content{margin-right:auto}#quarto-announcement .quarto-announcement-content p{margin-bottom:0}#quarto-announcement .quarto-announcement-icon{margin-right:.5em;font-size:1.2em;margin-top:-0.15em}#quarto-announcement .quarto-announcement-action{cursor:pointer}.aa-DetachedSearchButtonQuery{display:none}.aa-DetachedOverlay ul.aa-List,#quarto-search-results ul.aa-List{list-style:none;padding-left:0}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{background-color:#fff;position:absolute;z-index:2000}#quarto-search-results .aa-Panel{max-width:400px}#quarto-search input{font-size:.925rem}@media(min-width: 992px){.navbar #quarto-search{margin-left:.25rem;order:999}}.navbar.navbar-expand-sm #quarto-search,.navbar.navbar-expand-md #quarto-search{order:999}@media(min-width: 992px){.navbar .quarto-navbar-tools{order:900}}@media(min-width: 992px){.navbar .quarto-navbar-tools.tools-end{margin-left:auto !important}}@media(max-width: 991.98px){#quarto-sidebar .sidebar-search{display:none}}#quarto-sidebar .sidebar-search .aa-Autocomplete{width:100%}.navbar .aa-Autocomplete .aa-Form{width:180px}.navbar #quarto-search.type-overlay .aa-Autocomplete{width:40px}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form{background-color:inherit;border:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form:focus-within{box-shadow:none;outline:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper{display:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper:focus-within{display:inherit}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-Label svg,.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-LoadingIndicator svg{width:26px;height:26px;color:#222;opacity:1}.navbar #quarto-search.type-overlay .aa-Autocomplete svg.aa-SubmitIcon{width:26px;height:26px;color:#222;opacity:1}.aa-Autocomplete .aa-Form,.aa-DetachedFormContainer .aa-Form{align-items:center;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;color:#222;display:flex;line-height:1em;margin:0;position:relative;width:100%}.aa-Autocomplete .aa-Form:focus-within,.aa-DetachedFormContainer .aa-Form:focus-within{box-shadow:rgba(44,62,80,.6) 0 0 0 1px;outline:currentColor none medium}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix{align-items:center;display:flex;flex-shrink:0;order:1}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{cursor:initial;flex-shrink:0;padding:0;text-align:left}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg{color:#222;opacity:.5}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton{appearance:none;background:none;border:0;margin:0}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{align-items:center;display:flex;justify-content:center}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapper,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper{order:3;position:relative;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input{appearance:none;background:none;border:0;color:#222;font:inherit;height:calc(1.5em + .1rem + 2px);padding:0;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::placeholder,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::placeholder{color:#222;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input:focus{border-color:none;box-shadow:none;outline:none}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix{align-items:center;display:flex;order:4}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton{align-items:center;background:none;border:0;color:#222;opacity:.8;cursor:pointer;display:flex;margin:0;width:calc(1.5em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus{color:#222;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg{width:calc(1.5em + 0.75rem + calc(1px * 2))}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton{border:none;align-items:center;background:none;color:#222;opacity:.4;font-size:.7rem;cursor:pointer;display:none;margin:0;width:calc(1em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus{color:#222;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden]{display:none}.aa-PanelLayout:empty{display:none}.quarto-search-no-results.no-query{display:none}.aa-Source:has(.no-query){display:none}#quarto-search-results .aa-Panel{border:solid #dee2e6 1px}#quarto-search-results .aa-SourceNoResults{width:398px}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{max-height:65vh;overflow-y:auto;font-size:.925rem}.aa-DetachedOverlay .aa-SourceNoResults,#quarto-search-results .aa-SourceNoResults{height:60px;display:flex;justify-content:center;align-items:center}.aa-DetachedOverlay .search-error,#quarto-search-results .search-error{padding-top:10px;padding-left:20px;padding-right:20px;cursor:default}.aa-DetachedOverlay .search-error .search-error-title,#quarto-search-results .search-error .search-error-title{font-size:1.1rem;margin-bottom:.5rem}.aa-DetachedOverlay .search-error .search-error-title .search-error-icon,#quarto-search-results .search-error .search-error-title .search-error-icon{margin-right:8px}.aa-DetachedOverlay .search-error .search-error-text,#quarto-search-results .search-error .search-error-text{font-weight:300}.aa-DetachedOverlay .search-result-text,#quarto-search-results .search-result-text{font-weight:300;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.2rem;max-height:2.4rem}.aa-DetachedOverlay .aa-SourceHeader .search-result-header,#quarto-search-results .aa-SourceHeader .search-result-header{font-size:.875rem;background-color:#f2f2f2;padding-left:14px;padding-bottom:4px;padding-top:4px}.aa-DetachedOverlay .aa-SourceHeader .search-result-header-no-results,#quarto-search-results .aa-SourceHeader .search-result-header-no-results{display:none}.aa-DetachedOverlay .aa-SourceFooter .algolia-search-logo,#quarto-search-results .aa-SourceFooter .algolia-search-logo{width:110px;opacity:.85;margin:8px;float:right}.aa-DetachedOverlay .search-result-section,#quarto-search-results .search-result-section{font-size:.925em}.aa-DetachedOverlay a.search-result-link,#quarto-search-results a.search-result-link{color:inherit;text-decoration:none}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item,#quarto-search-results li.aa-Item[aria-selected=true] .search-item{background-color:#2c3e50}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text-container{color:#fff;background-color:#2c3e50}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=true] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-match.mark{color:#fff;background-color:#3a526a}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item,#quarto-search-results li.aa-Item[aria-selected=false] .search-item{background-color:#fff}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text-container{color:#222}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=false] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-match.mark{color:inherit;background-color:#90a9c2}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container{background-color:#fff;color:#222}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container{padding-top:0px}.aa-DetachedOverlay li.aa-Item .search-result-doc.document-selectable .search-result-text-container,#quarto-search-results li.aa-Item .search-result-doc.document-selectable .search-result-text-container{margin-top:-4px}.aa-DetachedOverlay .aa-Item,#quarto-search-results .aa-Item{cursor:pointer}.aa-DetachedOverlay .aa-Item .search-item,#quarto-search-results .aa-Item .search-item{border-left:none;border-right:none;border-top:none;background-color:#fff;border-color:#dee2e6;color:#222}.aa-DetachedOverlay .aa-Item .search-item p,#quarto-search-results .aa-Item .search-item p{margin-top:0;margin-bottom:0}.aa-DetachedOverlay .aa-Item .search-item i.bi,#quarto-search-results .aa-Item .search-item i.bi{padding-left:8px;padding-right:8px;font-size:1.3em}.aa-DetachedOverlay .aa-Item .search-item .search-result-title,#quarto-search-results .aa-Item .search-item .search-result-title{margin-top:.3em;margin-bottom:0em}.aa-DetachedOverlay .aa-Item .search-item .search-result-crumbs,#quarto-search-results .aa-Item .search-item .search-result-crumbs{white-space:nowrap;text-overflow:ellipsis;font-size:.8em;font-weight:300;margin-right:1em}.aa-DetachedOverlay .aa-Item .search-item .search-result-crumbs:not(.search-result-crumbs-wrap),#quarto-search-results .aa-Item .search-item .search-result-crumbs:not(.search-result-crumbs-wrap){max-width:30%;margin-left:auto;margin-top:.5em;margin-bottom:.1rem}.aa-DetachedOverlay .aa-Item .search-item .search-result-crumbs.search-result-crumbs-wrap,#quarto-search-results .aa-Item .search-item .search-result-crumbs.search-result-crumbs-wrap{flex-basis:100%;margin-top:0em;margin-bottom:.2em;margin-left:37px}.aa-DetachedOverlay .aa-Item .search-result-title-container,#quarto-search-results .aa-Item .search-result-title-container{font-size:1em;display:flex;flex-wrap:wrap;padding:6px 4px 6px 4px}.aa-DetachedOverlay .aa-Item .search-result-text-container,#quarto-search-results .aa-Item .search-result-text-container{padding-bottom:8px;padding-right:8px;margin-left:42px}.aa-DetachedOverlay .aa-Item .search-result-doc-section,.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-doc-section,#quarto-search-results .aa-Item .search-result-more{padding-top:8px;padding-bottom:8px;padding-left:44px}.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-more{font-size:.8em;font-weight:400}.aa-DetachedOverlay .aa-Item .search-result-doc,#quarto-search-results .aa-Item .search-result-doc{border-top:1px solid #dee2e6}.aa-DetachedSearchButton{background:none;border:none}.aa-DetachedSearchButton .aa-DetachedSearchButtonPlaceholder{display:none}.navbar .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#222}.sidebar-tools-collapse #quarto-search,.sidebar-tools-main #quarto-search{display:inline}.sidebar-tools-collapse #quarto-search .aa-Autocomplete,.sidebar-tools-main #quarto-search .aa-Autocomplete{display:inline}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton{padding-left:4px;padding-right:4px}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#222}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon{margin-top:-3px}.aa-DetachedContainer{background:rgba(255,255,255,.65);width:90%;bottom:0;box-shadow:rgba(222,226,230,.6) 0 0 0 1px;outline:currentColor none medium;display:flex;flex-direction:column;left:0;margin:0;overflow:hidden;padding:0;position:fixed;right:0;top:0;z-index:1101}.aa-DetachedContainer::after{height:32px}.aa-DetachedContainer .aa-SourceHeader{margin:var(--aa-spacing-half) 0 var(--aa-spacing-half) 2px}.aa-DetachedContainer .aa-Panel{background-color:#fff;border-radius:0;box-shadow:none;flex-grow:1;margin:0;padding:0;position:relative}.aa-DetachedContainer .aa-PanelLayout{bottom:0;box-shadow:none;left:0;margin:0;max-height:none;overflow-y:auto;position:absolute;right:0;top:0;width:100%}.aa-DetachedFormContainer{background-color:#fff;border-bottom:1px solid #dee2e6;display:flex;flex-direction:row;justify-content:space-between;margin:0;padding:.5em}.aa-DetachedCancelButton{background:none;font-size:.8em;border:0;border-radius:3px;color:#222;cursor:pointer;margin:0 0 0 .5em;padding:0 .5em}.aa-DetachedCancelButton:hover,.aa-DetachedCancelButton:focus{box-shadow:rgba(44,62,80,.6) 0 0 0 1px;outline:currentColor none medium}.aa-DetachedContainer--modal{bottom:inherit;height:auto;margin:0 auto;position:absolute;top:100px;border-radius:6px;max-width:850px}@media(max-width: 575.98px){.aa-DetachedContainer--modal{width:100%;top:0px;border-radius:0px;border:none}}.aa-DetachedContainer--modal .aa-PanelLayout{max-height:var(--aa-detached-modal-max-height);padding-bottom:var(--aa-spacing-half);position:static}.aa-Detached{height:100vh;overflow:hidden}.aa-DetachedOverlay{background-color:rgba(34,34,34,.4);position:fixed;left:0;right:0;top:0;margin:0;padding:0;height:100vh;z-index:1100}.quarto-dashboard.nav-fixed.dashboard-sidebar #quarto-content.quarto-dashboard-content{padding:0em}.quarto-dashboard #quarto-content.quarto-dashboard-content{padding:1em}.quarto-dashboard #quarto-content.quarto-dashboard-content>*{padding-top:0}@media(min-width: 576px){.quarto-dashboard{height:100%}}.quarto-dashboard .card.valuebox.bslib-card.bg-primary{background-color:rgba(39,128,227,.7) !important}.quarto-dashboard .card.valuebox.bslib-card.bg-secondary{background-color:#6c757d !important}.quarto-dashboard .card.valuebox.bslib-card.bg-success{background-color:rgba(63,182,24,.7) !important}.quarto-dashboard .card.valuebox.bslib-card.bg-info{background-color:rgba(153,84,187,.7) !important}.quarto-dashboard .card.valuebox.bslib-card.bg-warning{background-color:rgba(255,117,24,.7) !important}.quarto-dashboard .card.valuebox.bslib-card.bg-danger{background-color:rgba(255,0,57,.7) !important}.quarto-dashboard .card.valuebox.bslib-card.bg-light{background-color:#ecf0f1 !important}.quarto-dashboard .card.valuebox.bslib-card.bg-dark{background-color:#7b8a8b !important}.quarto-dashboard.dashboard-fill{display:flex;flex-direction:column}.quarto-dashboard #quarto-appendix{display:none}.quarto-dashboard #quarto-header #quarto-dashboard-header{border-top:solid 1px #d3d3d3;border-bottom:solid 1px #d3d3d3}.quarto-dashboard #quarto-header #quarto-dashboard-header>nav{padding-left:1em;padding-right:1em}.quarto-dashboard #quarto-header #quarto-dashboard-header>nav .navbar-brand-container{padding-left:0}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-toggler{margin-right:0}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-toggler-icon{height:1em;width:1em;background-image:url('data:image/svg+xml,')}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-brand-container{padding-right:1em}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-title{font-size:1.1em}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-nav{font-size:.9em}.quarto-dashboard #quarto-dashboard-header .navbar{padding:0}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-container{padding-left:1em}.quarto-dashboard #quarto-dashboard-header .navbar.slim .navbar-brand-container .nav-link,.quarto-dashboard #quarto-dashboard-header .navbar.slim .navbar-nav .nav-link{padding:.7em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-color-scheme-toggle{order:9}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-toggler{margin-left:.5em;order:10}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-nav .nav-link{padding:.5em;height:100%;display:flex;align-items:center}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-nav .active{background-color:#d8d8d8}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-brand-container{padding:.5em .5em .5em 0;display:flex;flex-direction:row;margin-right:2em;align-items:center}@media(max-width: 767.98px){.quarto-dashboard #quarto-dashboard-header .navbar .navbar-brand-container{margin-right:auto}}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse{align-self:stretch}@media(min-width: 768px){.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse{order:8}}@media(max-width: 767.98px){.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse{order:1000;padding-bottom:.5em}}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse .navbar-nav{align-self:stretch}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-title{font-size:1.25em;line-height:1.1em;display:flex;flex-direction:row;flex-wrap:wrap;align-items:baseline}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-title .navbar-title-text{margin-right:.4em}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-title a{text-decoration:none;color:inherit}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-subtitle,.quarto-dashboard #quarto-dashboard-header .navbar .navbar-author{font-size:.9rem;margin-right:.5em}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-author{margin-left:auto}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-logo{max-height:48px;min-height:30px;object-fit:cover;margin-right:1em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-dashboard-links{order:9;padding-right:1em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-dashboard-link-text{margin-left:.25em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-dashboard-link{padding-right:0em;padding-left:.7em;text-decoration:none;color:#222}.quarto-dashboard .page-layout-custom .tab-content{padding:0;border:none}.quarto-dashboard-img-contain{height:100%;width:100%;object-fit:contain}@media(max-width: 575.98px){.quarto-dashboard .bslib-grid{grid-template-rows:minmax(1em, max-content) !important}.quarto-dashboard .sidebar-content{height:inherit}.quarto-dashboard .page-layout-custom{min-height:100vh}}.quarto-dashboard.dashboard-toolbar>.page-layout-custom,.quarto-dashboard.dashboard-sidebar>.page-layout-custom{padding:0}.quarto-dashboard .quarto-dashboard-content.quarto-dashboard-pages{padding:0}.quarto-dashboard .callout{margin-bottom:0;margin-top:0}.quarto-dashboard .html-fill-container figure{overflow:hidden}.quarto-dashboard bslib-tooltip .rounded-pill{border:solid #6c757d 1px}.quarto-dashboard bslib-tooltip .rounded-pill .svg{fill:#222}.quarto-dashboard .tabset .dashboard-card-no-title .nav-tabs{margin-left:0;margin-right:auto}.quarto-dashboard .tabset .tab-content{border:none}.quarto-dashboard .tabset .card-header .nav-link[role=tab]{margin-top:-6px;padding-top:6px;padding-bottom:6px}.quarto-dashboard .card.valuebox,.quarto-dashboard .card.bslib-value-box{min-height:3rem}.quarto-dashboard .card.valuebox .card-body,.quarto-dashboard .card.bslib-value-box .card-body{padding:0}.quarto-dashboard .bslib-value-box .value-box-value{font-size:clamp(.1em,15cqw,5em)}.quarto-dashboard .bslib-value-box .value-box-showcase .bi{font-size:clamp(.1em,max(18cqw,5.2cqh),5em);text-align:center;height:1em}.quarto-dashboard .bslib-value-box .value-box-showcase .bi::before{vertical-align:1em}.quarto-dashboard .bslib-value-box .value-box-area{margin-top:auto;margin-bottom:auto}.quarto-dashboard .card figure.quarto-float{display:flex;flex-direction:column;align-items:center}.quarto-dashboard .dashboard-scrolling{padding:1em}.quarto-dashboard .full-height{height:100%}.quarto-dashboard .showcase-bottom .value-box-grid{display:grid;grid-template-columns:1fr;grid-template-rows:1fr auto;grid-template-areas:"top" "bottom"}.quarto-dashboard .showcase-bottom .value-box-grid .value-box-showcase{grid-area:bottom;padding:0;margin:0}.quarto-dashboard .showcase-bottom .value-box-grid .value-box-showcase i.bi{font-size:4rem}.quarto-dashboard .showcase-bottom .value-box-grid .value-box-area{grid-area:top}.quarto-dashboard .tab-content{margin-bottom:0}.quarto-dashboard .bslib-card .bslib-navs-card-title{justify-content:stretch;align-items:end}.quarto-dashboard .card-header{display:flex;flex-wrap:wrap;justify-content:space-between}.quarto-dashboard .card-header .card-title{display:flex;flex-direction:column;justify-content:center;margin-bottom:0}.quarto-dashboard .tabset .card-toolbar{margin-bottom:1em}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout{border:none;gap:var(--bslib-spacer, 1rem)}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.main{padding:0}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.sidebar{border-radius:.25rem;border:1px solid rgba(0,0,0,.175)}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.collapse-toggle{display:none}@media(max-width: 767.98px){.quarto-dashboard .bslib-grid>.bslib-sidebar-layout{grid-template-columns:1fr;grid-template-rows:max-content 1fr}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.main{grid-column:1;grid-row:2}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout .sidebar{grid-column:1;grid-row:1}}.quarto-dashboard .sidebar-right .sidebar{padding-left:2.5em}.quarto-dashboard .sidebar-right .collapse-toggle{left:2px}.quarto-dashboard .quarto-dashboard .sidebar-right button.collapse-toggle:not(.transitioning){left:unset}.quarto-dashboard aside.sidebar{padding-left:1em;padding-right:1em;background-color:rgba(52,58,64,.25);color:#222}.quarto-dashboard .bslib-sidebar-layout>div.main{padding:.7em}.quarto-dashboard .bslib-sidebar-layout button.collapse-toggle{margin-top:.3em}.quarto-dashboard .bslib-sidebar-layout .collapse-toggle{top:0}.quarto-dashboard .bslib-sidebar-layout.sidebar-collapsed:not(.transitioning):not(.sidebar-right) .collapse-toggle{left:2px}.quarto-dashboard .sidebar>section>.h3:first-of-type{margin-top:0em}.quarto-dashboard .sidebar .h3,.quarto-dashboard .sidebar .h4,.quarto-dashboard .sidebar .h5,.quarto-dashboard .sidebar .h6{margin-top:.5em}.quarto-dashboard .sidebar form{flex-direction:column;align-items:start;margin-bottom:1em}.quarto-dashboard .sidebar form div[class*=oi-][class$=-input]{flex-direction:column}.quarto-dashboard .sidebar form[class*=oi-][class$=-toggle]{flex-direction:row-reverse;align-items:center;justify-content:start}.quarto-dashboard .sidebar form input[type=range]{margin-top:.5em;margin-right:.8em;margin-left:1em}.quarto-dashboard .sidebar label{width:fit-content}.quarto-dashboard .sidebar .card-body{margin-bottom:2em}.quarto-dashboard .sidebar .shiny-input-container{margin-bottom:1em}.quarto-dashboard .sidebar .shiny-options-group{margin-top:0}.quarto-dashboard .sidebar .control-label{margin-bottom:.3em}.quarto-dashboard .card .card-body .quarto-layout-row{align-items:stretch}.quarto-dashboard .toolbar{font-size:.9em;display:flex;flex-direction:row;border-top:solid 1px #c7c9cd;padding:1em;flex-wrap:wrap;background-color:rgba(52,58,64,.25)}.quarto-dashboard .toolbar .cell-output-display{display:flex}.quarto-dashboard .toolbar .shiny-input-container{padding-bottom:.5em;margin-bottom:.5em;width:inherit}.quarto-dashboard .toolbar .shiny-input-container>.checkbox:first-child{margin-top:6px}.quarto-dashboard .toolbar>*:last-child{margin-right:0}.quarto-dashboard .toolbar>*>*{margin-right:1em;align-items:baseline}.quarto-dashboard .toolbar>*>*>a{text-decoration:none;margin-top:auto;margin-bottom:auto}.quarto-dashboard .toolbar .shiny-input-container{padding-bottom:0;margin-bottom:0}.quarto-dashboard .toolbar .shiny-input-container>*{flex-shrink:0;flex-grow:0}.quarto-dashboard .toolbar .form-group.shiny-input-container:not([role=group])>label{margin-bottom:0}.quarto-dashboard .toolbar .shiny-input-container.no-baseline{align-items:start;padding-top:6px}.quarto-dashboard .toolbar .shiny-input-container{display:flex;align-items:baseline}.quarto-dashboard .toolbar .shiny-input-container label{padding-right:.4em}.quarto-dashboard .toolbar .shiny-input-container .bslib-input-switch{margin-top:6px}.quarto-dashboard .toolbar input[type=text]{line-height:1;width:inherit}.quarto-dashboard .toolbar .input-daterange{width:inherit}.quarto-dashboard .toolbar .input-daterange input[type=text]{height:2.4em;width:10em}.quarto-dashboard .toolbar .input-daterange .input-group-addon{height:auto;padding:0;margin-left:-5px !important;margin-right:-5px}.quarto-dashboard .toolbar .input-daterange .input-group-addon .input-group-text{padding-top:0;padding-bottom:0;height:100%}.quarto-dashboard .toolbar span.irs.irs--shiny{width:10em}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-line{top:9px}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-min,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-max,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-from,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-to,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-single{top:20px}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-bar{top:8px}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-handle{top:0px}.quarto-dashboard .toolbar .shiny-input-checkboxgroup>label{margin-top:6px}.quarto-dashboard .toolbar .shiny-input-checkboxgroup>.shiny-options-group{margin-top:0;align-items:baseline}.quarto-dashboard .toolbar .shiny-input-radiogroup>label{margin-top:6px}.quarto-dashboard .toolbar .shiny-input-radiogroup>.shiny-options-group{align-items:baseline;margin-top:0}.quarto-dashboard .toolbar .shiny-input-radiogroup>.shiny-options-group>.radio{margin-right:.3em}.quarto-dashboard .toolbar .form-select{padding-top:.2em;padding-bottom:.2em}.quarto-dashboard .toolbar .shiny-input-select{min-width:6em}.quarto-dashboard .toolbar div.checkbox{margin-bottom:0px}.quarto-dashboard .toolbar>.checkbox:first-child{margin-top:6px}.quarto-dashboard .toolbar form{width:fit-content}.quarto-dashboard .toolbar form label{padding-top:.2em;padding-bottom:.2em;width:fit-content}.quarto-dashboard .toolbar form input[type=date]{width:fit-content}.quarto-dashboard .toolbar form input[type=color]{width:3em}.quarto-dashboard .toolbar form button{padding:.4em}.quarto-dashboard .toolbar form select{width:fit-content}.quarto-dashboard .toolbar>*{font-size:.9em;flex-grow:0}.quarto-dashboard .toolbar .shiny-input-container label{margin-bottom:1px}.quarto-dashboard .toolbar-bottom{margin-top:1em;margin-bottom:0 !important;order:2}.quarto-dashboard .quarto-dashboard-content>.dashboard-toolbar-container>.toolbar-content>.tab-content>.tab-pane>*:not(.bslib-sidebar-layout){padding:1em}.quarto-dashboard .quarto-dashboard-content>.dashboard-toolbar-container>.toolbar-content>*:not(.tab-content){padding:1em}.quarto-dashboard .quarto-dashboard-content>.tab-content>.dashboard-page>.dashboard-toolbar-container>.toolbar-content,.quarto-dashboard .quarto-dashboard-content>.tab-content>.dashboard-page:not(.dashboard-sidebar-container)>*:not(.dashboard-toolbar-container){padding:1em}.quarto-dashboard .toolbar-content{padding:0}.quarto-dashboard .quarto-dashboard-content.quarto-dashboard-pages .tab-pane>.dashboard-toolbar-container .toolbar{border-radius:0;margin-bottom:0}.quarto-dashboard .dashboard-toolbar-container.toolbar-toplevel .toolbar{border-bottom:1px solid rgba(0,0,0,.175)}.quarto-dashboard .dashboard-toolbar-container.toolbar-toplevel .toolbar-bottom{margin-top:0}.quarto-dashboard .dashboard-toolbar-container:not(.toolbar-toplevel) .toolbar{margin-bottom:1em;border-top:none;border-radius:.25rem;border:1px solid rgba(0,0,0,.175)}.quarto-dashboard .vega-embed.has-actions details{width:1.7em;height:2em;position:absolute !important;top:0;right:0}.quarto-dashboard .dashboard-toolbar-container{padding:0}.quarto-dashboard .card .card-header p:last-child,.quarto-dashboard .card .card-footer p:last-child{margin-bottom:0}.quarto-dashboard .card .card-body>.h4:first-child{margin-top:0}.quarto-dashboard .card .card-body{z-index:4}@media(max-width: 767.98px){.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_length,.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_info,.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_paginate{text-align:initial}.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_filter{text-align:right}.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_paginate ul.pagination{justify-content:initial}}.quarto-dashboard .card .card-body .itables .dataTables_wrapper{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;padding-top:0}.quarto-dashboard .card .card-body .itables .dataTables_wrapper table{flex-shrink:0}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons{margin-bottom:.5em;margin-left:auto;width:fit-content;float:right}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons.btn-group{background:#fff;border:none}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons .btn-secondary{background-color:#fff;background-image:none;border:solid #dee2e6 1px;padding:.2em .7em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons .btn span{font-size:.8em;color:#222}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_info{margin-left:.5em;margin-bottom:.5em;padding-top:0}@media(min-width: 768px){.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_info{font-size:.875em}}@media(max-width: 767.98px){.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_info{font-size:.8em}}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_filter{margin-bottom:.5em;font-size:.875em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_filter input[type=search]{padding:1px 5px 1px 5px;font-size:.875em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_length{flex-basis:1 1 50%;margin-bottom:.5em;font-size:.875em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_length select{padding:.4em 3em .4em .5em;font-size:.875em;margin-left:.2em;margin-right:.2em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_paginate{flex-shrink:0}@media(min-width: 768px){.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_paginate{margin-left:auto}}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_paginate ul.pagination .paginate_button .page-link{font-size:.8em}.quarto-dashboard .card .card-footer{font-size:.9em}.quarto-dashboard .card .card-toolbar{display:flex;flex-grow:1;flex-direction:row;width:100%;flex-wrap:wrap}.quarto-dashboard .card .card-toolbar>*{font-size:.8em;flex-grow:0}.quarto-dashboard .card .card-toolbar>.card-title{font-size:1em;flex-grow:1;align-self:flex-start;margin-top:.1em}.quarto-dashboard .card .card-toolbar .cell-output-display{display:flex}.quarto-dashboard .card .card-toolbar .shiny-input-container{padding-bottom:.5em;margin-bottom:.5em;width:inherit}.quarto-dashboard .card .card-toolbar .shiny-input-container>.checkbox:first-child{margin-top:6px}.quarto-dashboard .card .card-toolbar>*:last-child{margin-right:0}.quarto-dashboard .card .card-toolbar>*>*{margin-right:1em;align-items:baseline}.quarto-dashboard .card .card-toolbar>*>*>a{text-decoration:none;margin-top:auto;margin-bottom:auto}.quarto-dashboard .card .card-toolbar form{width:fit-content}.quarto-dashboard .card .card-toolbar form label{padding-top:.2em;padding-bottom:.2em;width:fit-content}.quarto-dashboard .card .card-toolbar form input[type=date]{width:fit-content}.quarto-dashboard .card .card-toolbar form input[type=color]{width:3em}.quarto-dashboard .card .card-toolbar form button{padding:.4em}.quarto-dashboard .card .card-toolbar form select{width:fit-content}.quarto-dashboard .card .card-toolbar .cell-output-display{display:flex}.quarto-dashboard .card .card-toolbar .shiny-input-container{padding-bottom:.5em;margin-bottom:.5em;width:inherit}.quarto-dashboard .card .card-toolbar .shiny-input-container>.checkbox:first-child{margin-top:6px}.quarto-dashboard .card .card-toolbar>*:last-child{margin-right:0}.quarto-dashboard .card .card-toolbar>*>*{margin-right:1em;align-items:baseline}.quarto-dashboard .card .card-toolbar>*>*>a{text-decoration:none;margin-top:auto;margin-bottom:auto}.quarto-dashboard .card .card-toolbar .shiny-input-container{padding-bottom:0;margin-bottom:0}.quarto-dashboard .card .card-toolbar .shiny-input-container>*{flex-shrink:0;flex-grow:0}.quarto-dashboard .card .card-toolbar .form-group.shiny-input-container:not([role=group])>label{margin-bottom:0}.quarto-dashboard .card .card-toolbar .shiny-input-container.no-baseline{align-items:start;padding-top:6px}.quarto-dashboard .card .card-toolbar .shiny-input-container{display:flex;align-items:baseline}.quarto-dashboard .card .card-toolbar .shiny-input-container label{padding-right:.4em}.quarto-dashboard .card .card-toolbar .shiny-input-container .bslib-input-switch{margin-top:6px}.quarto-dashboard .card .card-toolbar input[type=text]{line-height:1;width:inherit}.quarto-dashboard .card .card-toolbar .input-daterange{width:inherit}.quarto-dashboard .card .card-toolbar .input-daterange input[type=text]{height:2.4em;width:10em}.quarto-dashboard .card .card-toolbar .input-daterange .input-group-addon{height:auto;padding:0;margin-left:-5px !important;margin-right:-5px}.quarto-dashboard .card .card-toolbar .input-daterange .input-group-addon .input-group-text{padding-top:0;padding-bottom:0;height:100%}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny{width:10em}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-line{top:9px}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-min,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-max,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-from,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-to,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-single{top:20px}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-bar{top:8px}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-handle{top:0px}.quarto-dashboard .card .card-toolbar .shiny-input-checkboxgroup>label{margin-top:6px}.quarto-dashboard .card .card-toolbar .shiny-input-checkboxgroup>.shiny-options-group{margin-top:0;align-items:baseline}.quarto-dashboard .card .card-toolbar .shiny-input-radiogroup>label{margin-top:6px}.quarto-dashboard .card .card-toolbar .shiny-input-radiogroup>.shiny-options-group{align-items:baseline;margin-top:0}.quarto-dashboard .card .card-toolbar .shiny-input-radiogroup>.shiny-options-group>.radio{margin-right:.3em}.quarto-dashboard .card .card-toolbar .form-select{padding-top:.2em;padding-bottom:.2em}.quarto-dashboard .card .card-toolbar .shiny-input-select{min-width:6em}.quarto-dashboard .card .card-toolbar div.checkbox{margin-bottom:0px}.quarto-dashboard .card .card-toolbar>.checkbox:first-child{margin-top:6px}.quarto-dashboard .card-body>table>thead{border-top:none}.quarto-dashboard .card-body>.table>:not(caption)>*>*{background-color:#fff}.tableFloatingHeaderOriginal{background-color:#fff;position:sticky !important;top:0 !important}.dashboard-data-table{margin-top:-1px}div.value-box-area span.observablehq--number{font-size:calc(clamp(.1em,15cqw,5em)*1.25);line-height:1.2;color:inherit;font-family:var(--bs-body-font-family)}.quarto-listing{padding-bottom:1em}.listing-pagination{padding-top:.5em}ul.pagination{float:right;padding-left:8px;padding-top:.5em}ul.pagination li{padding-right:.75em}ul.pagination li.disabled a,ul.pagination li.active a{color:#fff;text-decoration:none}ul.pagination li:last-of-type{padding-right:0}.listing-actions-group{display:flex}.quarto-listing-filter{margin-bottom:1em;width:200px;margin-left:auto}.quarto-listing-sort{margin-bottom:1em;margin-right:auto;width:auto}.quarto-listing-sort .input-group-text{font-size:.8em}.input-group-text{border-right:none}.quarto-listing-sort select.form-select{font-size:.8em}.listing-no-matching{text-align:center;padding-top:2em;padding-bottom:3em;font-size:1em}#quarto-margin-sidebar .quarto-listing-category{padding-top:0;font-size:1rem}#quarto-margin-sidebar .quarto-listing-category-title{cursor:pointer;font-weight:600;font-size:1rem}.quarto-listing-category .category{cursor:pointer}.quarto-listing-category .category.active{font-weight:600}.quarto-listing-category.category-cloud{display:flex;flex-wrap:wrap;align-items:baseline}.quarto-listing-category.category-cloud .category{padding-right:5px}.quarto-listing-category.category-cloud .category-cloud-1{font-size:.75em}.quarto-listing-category.category-cloud .category-cloud-2{font-size:.95em}.quarto-listing-category.category-cloud .category-cloud-3{font-size:1.15em}.quarto-listing-category.category-cloud .category-cloud-4{font-size:1.35em}.quarto-listing-category.category-cloud .category-cloud-5{font-size:1.55em}.quarto-listing-category.category-cloud .category-cloud-6{font-size:1.75em}.quarto-listing-category.category-cloud .category-cloud-7{font-size:1.95em}.quarto-listing-category.category-cloud .category-cloud-8{font-size:2.15em}.quarto-listing-category.category-cloud .category-cloud-9{font-size:2.35em}.quarto-listing-category.category-cloud .category-cloud-10{font-size:2.55em}.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-1{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-2{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-3{grid-template-columns:repeat(3, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-3{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-3{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-4{grid-template-columns:repeat(4, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-4{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-4{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-5{grid-template-columns:repeat(5, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-5{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-5{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-6{grid-template-columns:repeat(6, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-6{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-6{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-7{grid-template-columns:repeat(7, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-7{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-7{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-8{grid-template-columns:repeat(8, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-8{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-8{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-9{grid-template-columns:repeat(9, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-9{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-9{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-10{grid-template-columns:repeat(10, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-10{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-10{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-11{grid-template-columns:repeat(11, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-11{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-11{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-12{grid-template-columns:repeat(12, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-12{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-12{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-grid{gap:1.5em}.quarto-grid-item.borderless{border:none}.quarto-grid-item.borderless .listing-categories .listing-category:last-of-type,.quarto-grid-item.borderless .listing-categories .listing-category:first-of-type{padding-left:0}.quarto-grid-item.borderless .listing-categories .listing-category{border:0}.quarto-grid-link{text-decoration:none;color:inherit}.quarto-grid-link:hover{text-decoration:none;color:inherit}.quarto-grid-item h5.title,.quarto-grid-item .title.h5{margin-top:0;margin-bottom:0}.quarto-grid-item .card-footer{display:flex;justify-content:space-between;font-size:.8em}.quarto-grid-item .card-footer p{margin-bottom:0}.quarto-grid-item p.card-img-top{margin-bottom:0}.quarto-grid-item p.card-img-top>img{object-fit:cover}.quarto-grid-item .card-other-values{margin-top:.5em;font-size:.8em}.quarto-grid-item .card-other-values tr{margin-bottom:.5em}.quarto-grid-item .card-other-values tr>td:first-of-type{font-weight:600;padding-right:1em;padding-left:1em;vertical-align:top}.quarto-grid-item div.post-contents{display:flex;flex-direction:column;text-decoration:none;height:100%}.quarto-grid-item .listing-item-img-placeholder{background-color:rgba(52,58,64,.25);flex-shrink:0}.quarto-grid-item .card-attribution{padding-top:1em;display:flex;gap:1em;text-transform:uppercase;color:#6c757d;font-weight:500;flex-grow:10;align-items:flex-end}.quarto-grid-item .description{padding-bottom:1em}.quarto-grid-item .card-attribution .date{align-self:flex-end}.quarto-grid-item .card-attribution.justify{justify-content:space-between}.quarto-grid-item .card-attribution.start{justify-content:flex-start}.quarto-grid-item .card-attribution.end{justify-content:flex-end}.quarto-grid-item .card-title{margin-bottom:.1em}.quarto-grid-item .card-subtitle{padding-top:.25em}.quarto-grid-item .card-text{font-size:.9em}.quarto-grid-item .listing-reading-time{padding-bottom:.25em}.quarto-grid-item .card-text-small{font-size:.8em}.quarto-grid-item .card-subtitle.subtitle{font-size:.9em;font-weight:600;padding-bottom:.5em}.quarto-grid-item .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}.quarto-grid-item .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}.quarto-grid-item.card-right{text-align:right}.quarto-grid-item.card-right .listing-categories{justify-content:flex-end}.quarto-grid-item.card-left{text-align:left}.quarto-grid-item.card-center{text-align:center}.quarto-grid-item.card-center .listing-description{text-align:justify}.quarto-grid-item.card-center .listing-categories{justify-content:center}table.quarto-listing-table td.image{padding:0px}table.quarto-listing-table td.image img{width:100%;max-width:50px;object-fit:contain}table.quarto-listing-table a{text-decoration:none;word-break:keep-all}table.quarto-listing-table th a{color:inherit}table.quarto-listing-table th a.asc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table th a.desc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table.table-hover td{cursor:pointer}.quarto-post.image-left{flex-direction:row}.quarto-post.image-right{flex-direction:row-reverse}@media(max-width: 767.98px){.quarto-post.image-right,.quarto-post.image-left{gap:0em;flex-direction:column}.quarto-post .metadata{padding-bottom:1em;order:2}.quarto-post .body{order:1}.quarto-post .thumbnail{order:3}}.list.quarto-listing-default div:last-of-type{border-bottom:none}@media(min-width: 992px){.quarto-listing-container-default{margin-right:2em}}div.quarto-post{display:flex;gap:2em;margin-bottom:1.5em;border-bottom:1px solid #dee2e6}@media(max-width: 767.98px){div.quarto-post{padding-bottom:1em}}div.quarto-post .metadata{flex-basis:20%;flex-grow:0;margin-top:.2em;flex-shrink:10}div.quarto-post .thumbnail{flex-basis:30%;flex-grow:0;flex-shrink:0}div.quarto-post .thumbnail img{margin-top:.4em;width:100%;object-fit:cover}div.quarto-post .body{flex-basis:45%;flex-grow:1;flex-shrink:0}div.quarto-post .body h3.listing-title,div.quarto-post .body .listing-title.h3{margin-top:0px;margin-bottom:0px;border-bottom:none}div.quarto-post .body .listing-subtitle{font-size:.875em;margin-bottom:.5em;margin-top:.2em}div.quarto-post .body .description{font-size:.9em}div.quarto-post .body pre code{white-space:pre-wrap}div.quarto-post a{color:#222;text-decoration:none}div.quarto-post .metadata{display:flex;flex-direction:column;font-size:.8em;font-family:"Lato";flex-basis:33%}div.quarto-post .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}div.quarto-post .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}div.quarto-post .listing-description{margin-bottom:.5em}div.quarto-about-jolla{display:flex !important;flex-direction:column;align-items:center;margin-top:10%;padding-bottom:1em}div.quarto-about-jolla .about-image{object-fit:cover;margin-left:auto;margin-right:auto;margin-bottom:1.5em}div.quarto-about-jolla img.round{border-radius:50%}div.quarto-about-jolla img.rounded{border-radius:10px}div.quarto-about-jolla .quarto-title h1.title,div.quarto-about-jolla .quarto-title .title.h1{text-align:center}div.quarto-about-jolla .quarto-title .description{text-align:center}div.quarto-about-jolla h2,div.quarto-about-jolla .h2{border-bottom:none}div.quarto-about-jolla .about-sep{width:60%}div.quarto-about-jolla main{text-align:center}div.quarto-about-jolla .about-links{display:flex}@media(min-width: 992px){div.quarto-about-jolla .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-jolla .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-jolla .about-link{color:#555;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-jolla .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-jolla .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-jolla .about-link:hover{color:#5e7ca1}div.quarto-about-jolla .about-link i.bi{margin-right:.15em}div.quarto-about-solana{display:flex !important;flex-direction:column;padding-top:3em !important;padding-bottom:1em}div.quarto-about-solana .about-entity{display:flex !important;align-items:start;justify-content:space-between}@media(min-width: 992px){div.quarto-about-solana .about-entity{flex-direction:row}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity{flex-direction:column-reverse;align-items:center;text-align:center}}div.quarto-about-solana .about-entity .entity-contents{display:flex;flex-direction:column}@media(max-width: 767.98px){div.quarto-about-solana .about-entity .entity-contents{width:100%}}div.quarto-about-solana .about-entity .about-image{object-fit:cover}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-image{margin-bottom:1.5em}}div.quarto-about-solana .about-entity img.round{border-radius:50%}div.quarto-about-solana .about-entity img.rounded{border-radius:10px}div.quarto-about-solana .about-entity .about-links{display:flex;justify-content:left;padding-bottom:1.2em}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-solana .about-entity .about-link{color:#555;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-solana .about-entity .about-link:hover{color:#5e7ca1}div.quarto-about-solana .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-solana .about-contents{padding-right:1.5em;flex-basis:0;flex-grow:1}div.quarto-about-solana .about-contents main.content{margin-top:0}div.quarto-about-solana .about-contents h2,div.quarto-about-solana .about-contents .h2{border-bottom:none}div.quarto-about-trestles{display:flex !important;flex-direction:row;padding-top:3em !important;padding-bottom:1em}@media(max-width: 991.98px){div.quarto-about-trestles{flex-direction:column;padding-top:0em !important}}div.quarto-about-trestles .about-entity{display:flex !important;flex-direction:column;align-items:center;text-align:center;padding-right:1em}@media(min-width: 992px){div.quarto-about-trestles .about-entity{flex:0 0 42%}}div.quarto-about-trestles .about-entity .about-image{object-fit:cover;margin-bottom:1.5em}div.quarto-about-trestles .about-entity img.round{border-radius:50%}div.quarto-about-trestles .about-entity img.rounded{border-radius:10px}div.quarto-about-trestles .about-entity .about-links{display:flex;justify-content:center}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-trestles .about-entity .about-link{color:#555;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-trestles .about-entity .about-link:hover{color:#5e7ca1}div.quarto-about-trestles .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-trestles .about-contents{flex-basis:0;flex-grow:1}div.quarto-about-trestles .about-contents h2,div.quarto-about-trestles .about-contents .h2{border-bottom:none}@media(min-width: 992px){div.quarto-about-trestles .about-contents{border-left:solid 1px #dee2e6;padding-left:1.5em}}div.quarto-about-trestles .about-contents main.content{margin-top:0}div.quarto-about-marquee{padding-bottom:1em}div.quarto-about-marquee .about-contents{display:flex;flex-direction:column}div.quarto-about-marquee .about-image{max-height:550px;margin-bottom:1.5em;object-fit:cover}div.quarto-about-marquee img.round{border-radius:50%}div.quarto-about-marquee img.rounded{border-radius:10px}div.quarto-about-marquee h2,div.quarto-about-marquee .h2{border-bottom:none}div.quarto-about-marquee .about-links{display:flex;justify-content:center;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-marquee .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-marquee .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-marquee .about-link{color:#555;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-marquee .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-marquee .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-marquee .about-link:hover{color:#5e7ca1}div.quarto-about-marquee .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-marquee .about-link{border:none}}div.quarto-about-broadside{display:flex;flex-direction:column;padding-bottom:1em}div.quarto-about-broadside .about-main{display:flex !important;padding-top:0 !important}@media(min-width: 992px){div.quarto-about-broadside .about-main{flex-direction:row;align-items:flex-start}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main{flex-direction:column}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main .about-entity{flex-shrink:0;width:100%;height:450px;margin-bottom:1.5em;background-size:cover;background-repeat:no-repeat}}@media(min-width: 992px){div.quarto-about-broadside .about-main .about-entity{flex:0 10 50%;margin-right:1.5em;width:100%;height:100%;background-size:100%;background-repeat:no-repeat}}div.quarto-about-broadside .about-main .about-contents{padding-top:14px;flex:0 0 50%}div.quarto-about-broadside h2,div.quarto-about-broadside .h2{border-bottom:none}div.quarto-about-broadside .about-sep{margin-top:1.5em;width:60%;align-self:center}div.quarto-about-broadside .about-links{display:flex;justify-content:center;column-gap:20px;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-broadside .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-broadside .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-broadside .about-link{color:#555;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-broadside .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-broadside .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-broadside .about-link:hover{color:#5e7ca1}div.quarto-about-broadside .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-broadside .about-link{border:none}}.tippy-box[data-theme~=quarto]{background-color:#fff;border:solid 1px #dee2e6;border-radius:.25rem;color:#222;font-size:.875rem}.tippy-box[data-theme~=quarto]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=quarto]>.tippy-arrow:after,.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{content:"";position:absolute;z-index:-1}.tippy-box[data-theme~=quarto]>.tippy-arrow:after{border-color:rgba(0,0,0,0);border-style:solid}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-6px}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-6px}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-6px}.tippy-box[data-placement^=left]>.tippy-arrow:before{right:-6px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:after{border-top-color:#dee2e6;border-width:7px 7px 0;top:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow>svg{top:16px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow:after{top:17px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff;bottom:16px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:after{border-bottom-color:#dee2e6;border-width:0 7px 7px;bottom:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow>svg{bottom:15px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow:after{bottom:17px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:after{border-left-color:#dee2e6;border-width:7px 0 7px 7px;left:17px;top:1px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow>svg{left:11px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow:after{left:12px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff;right:16px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:after{border-width:7px 7px 7px 0;right:17px;top:1px;border-right-color:#dee2e6}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow>svg{right:11px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow:after{right:12px}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow{fill:#222}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiLz48L3N2Zz4=);background-size:16px 6px;width:16px;height:6px}.top-right{position:absolute;top:1em;right:1em}.visually-hidden{border:0;clip:rect(0 0 0 0);height:auto;margin:0;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.hidden{display:none !important}.zindex-bottom{z-index:-1 !important}figure.figure{display:block}.quarto-layout-panel{margin-bottom:1em}.quarto-layout-panel>figure{width:100%}.quarto-layout-panel>figure>figcaption,.quarto-layout-panel>.panel-caption{margin-top:10pt}.quarto-layout-panel>.table-caption{margin-top:0px}.table-caption p{margin-bottom:.5em}.quarto-layout-row{display:flex;flex-direction:row;align-items:flex-start}.quarto-layout-valign-top{align-items:flex-start}.quarto-layout-valign-bottom{align-items:flex-end}.quarto-layout-valign-center{align-items:center}.quarto-layout-cell{position:relative;margin-right:20px}.quarto-layout-cell:last-child{margin-right:0}.quarto-layout-cell figure,.quarto-layout-cell>p{margin:.2em}.quarto-layout-cell img{max-width:100%}.quarto-layout-cell .html-widget{width:100% !important}.quarto-layout-cell div figure p{margin:0}.quarto-layout-cell figure{display:block;margin-inline-start:0;margin-inline-end:0}.quarto-layout-cell table{display:inline-table}.quarto-layout-cell-subref figcaption,figure .quarto-layout-row figure figcaption{text-align:center;font-style:italic}.quarto-figure{position:relative;margin-bottom:1em}.quarto-figure>figure{width:100%;margin-bottom:0}.quarto-figure-left>figure>p,.quarto-figure-left>figure>div{text-align:left}.quarto-figure-center>figure>p,.quarto-figure-center>figure>div{text-align:center}.quarto-figure-right>figure>p,.quarto-figure-right>figure>div{text-align:right}.quarto-figure>figure>div.cell-annotation,.quarto-figure>figure>div code{text-align:left}figure>p:empty{display:none}figure>p:first-child{margin-top:0;margin-bottom:0}figure>figcaption.quarto-float-caption-bottom{margin-bottom:.5em}figure>figcaption.quarto-float-caption-top{margin-top:.5em}div[id^=tbl-]{position:relative}.quarto-figure>.anchorjs-link{position:absolute;top:.6em;right:.5em}div[id^=tbl-]>.anchorjs-link{position:absolute;top:.7em;right:.3em}.quarto-figure:hover>.anchorjs-link,div[id^=tbl-]:hover>.anchorjs-link,h2:hover>.anchorjs-link,.h2:hover>.anchorjs-link,h3:hover>.anchorjs-link,.h3:hover>.anchorjs-link,h4:hover>.anchorjs-link,.h4:hover>.anchorjs-link,h5:hover>.anchorjs-link,.h5:hover>.anchorjs-link,h6:hover>.anchorjs-link,.h6:hover>.anchorjs-link,.reveal-anchorjs-link>.anchorjs-link{opacity:1}#title-block-header{margin-block-end:1rem;position:relative;margin-top:-1px}#title-block-header .abstract{margin-block-start:1rem}#title-block-header .abstract .abstract-title{font-weight:600}#title-block-header a{text-decoration:none}#title-block-header .author,#title-block-header .date,#title-block-header .doi{margin-block-end:.2rem}#title-block-header .quarto-title-block>div{display:flex}#title-block-header .quarto-title-block>div>h1,#title-block-header .quarto-title-block>div>.h1{flex-grow:1}#title-block-header .quarto-title-block>div>button{flex-shrink:0;height:2.25rem;margin-top:0}@media(min-width: 992px){#title-block-header .quarto-title-block>div>button{margin-top:5px}}tr.header>th>p:last-of-type{margin-bottom:0px}table,table.table{margin-top:.5rem;margin-bottom:.5rem}caption,.table-caption{padding-top:.5rem;padding-bottom:.5rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-top{margin-top:.5rem;margin-bottom:.25rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-bottom{padding-top:.25rem;margin-bottom:.5rem;text-align:center}.utterances{max-width:none;margin-left:-8px}iframe{margin-bottom:1em}details{margin-bottom:1em}details[show]{margin-bottom:0}details>summary{color:#6c757d}details>summary>p:only-child{display:inline}pre.sourceCode,code.sourceCode{position:relative}p code:not(.sourceCode){white-space:pre-wrap}code{white-space:pre}@media print{code{white-space:pre-wrap}}pre>code{display:block}pre>code.sourceCode{white-space:pre}pre>code.sourceCode>span>a:first-child::before{text-decoration:none}pre.code-overflow-wrap>code.sourceCode{white-space:pre-wrap}pre.code-overflow-scroll>code.sourceCode{white-space:pre}code a:any-link{color:inherit;text-decoration:none}code a:hover{color:inherit;text-decoration:underline}ul.task-list{padding-left:1em}[data-tippy-root]{display:inline-block}.tippy-content .footnote-back{display:none}.footnote-back{margin-left:.2em}.tippy-content{overflow-x:auto}.quarto-embedded-source-code{display:none}.quarto-unresolved-ref{font-weight:600}.quarto-cover-image{max-width:35%;float:right;margin-left:30px}.cell-output-display .widget-subarea{margin-bottom:1em}.cell-output-display:not(.no-overflow-x),.knitsql-table:not(.no-overflow-x){overflow-x:auto}.panel-input{margin-bottom:1em}.panel-input>div,.panel-input>div>div{display:inline-block;vertical-align:top;padding-right:12px}.panel-input>p:last-child{margin-bottom:0}.layout-sidebar{margin-bottom:1em}.layout-sidebar .tab-content{border:none}.tab-content>.page-columns.active{display:grid}div.sourceCode>iframe{width:100%;height:300px;margin-bottom:-0.5em}a{text-underline-offset:3px}div.ansi-escaped-output{font-family:monospace;display:block}/*! +* +* ansi colors from IPython notebook's +* +* we also add `bright-[color]-` synonyms for the `-[color]-intense` classes since +* that seems to be what ansi_up emits +* +*/.ansi-black-fg{color:#3e424d}.ansi-black-bg{background-color:#3e424d}.ansi-black-intense-black,.ansi-bright-black-fg{color:#282c36}.ansi-black-intense-black,.ansi-bright-black-bg{background-color:#282c36}.ansi-red-fg{color:#e75c58}.ansi-red-bg{background-color:#e75c58}.ansi-red-intense-red,.ansi-bright-red-fg{color:#b22b31}.ansi-red-intense-red,.ansi-bright-red-bg{background-color:#b22b31}.ansi-green-fg{color:#00a250}.ansi-green-bg{background-color:#00a250}.ansi-green-intense-green,.ansi-bright-green-fg{color:#007427}.ansi-green-intense-green,.ansi-bright-green-bg{background-color:#007427}.ansi-yellow-fg{color:#ddb62b}.ansi-yellow-bg{background-color:#ddb62b}.ansi-yellow-intense-yellow,.ansi-bright-yellow-fg{color:#b27d12}.ansi-yellow-intense-yellow,.ansi-bright-yellow-bg{background-color:#b27d12}.ansi-blue-fg{color:#208ffb}.ansi-blue-bg{background-color:#208ffb}.ansi-blue-intense-blue,.ansi-bright-blue-fg{color:#0065ca}.ansi-blue-intense-blue,.ansi-bright-blue-bg{background-color:#0065ca}.ansi-magenta-fg{color:#d160c4}.ansi-magenta-bg{background-color:#d160c4}.ansi-magenta-intense-magenta,.ansi-bright-magenta-fg{color:#a03196}.ansi-magenta-intense-magenta,.ansi-bright-magenta-bg{background-color:#a03196}.ansi-cyan-fg{color:#60c6c8}.ansi-cyan-bg{background-color:#60c6c8}.ansi-cyan-intense-cyan,.ansi-bright-cyan-fg{color:#258f8f}.ansi-cyan-intense-cyan,.ansi-bright-cyan-bg{background-color:#258f8f}.ansi-white-fg{color:#c5c1b4}.ansi-white-bg{background-color:#c5c1b4}.ansi-white-intense-white,.ansi-bright-white-fg{color:#a1a6b2}.ansi-white-intense-white,.ansi-bright-white-bg{background-color:#a1a6b2}.ansi-default-inverse-fg{color:#fff}.ansi-default-inverse-bg{background-color:#000}.ansi-bold{font-weight:bold}.ansi-underline{text-decoration:underline}:root{--quarto-body-bg: #fff;--quarto-body-color: #222;--quarto-text-muted: #6c757d;--quarto-border-color: #dee2e6;--quarto-border-width: 1px;--quarto-border-radius: 0.25rem}table.gt_table{color:var(--quarto-body-color);font-size:1em;width:100%;background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_column_spanner_outer{color:var(--quarto-body-color);background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_col_heading{color:var(--quarto-body-color);font-weight:bold;background-color:rgba(0,0,0,0)}table.gt_table thead.gt_col_headings{border-bottom:1px solid currentColor;border-top-width:inherit;border-top-color:var(--quarto-border-color)}table.gt_table thead.gt_col_headings:not(:first-child){border-top-width:1px;border-top-color:var(--quarto-border-color)}table.gt_table td.gt_row{border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-width:0px}table.gt_table tbody.gt_table_body{border-top-width:1px;border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-color:currentColor}div.columns{display:initial;gap:initial}div.column{display:inline-block;overflow-x:initial;vertical-align:top;width:50%}.code-annotation-tip-content{word-wrap:break-word}.code-annotation-container-hidden{display:none !important}dl.code-annotation-container-grid{display:grid;grid-template-columns:min-content auto}dl.code-annotation-container-grid dt{grid-column:1}dl.code-annotation-container-grid dd{grid-column:2}pre.sourceCode.code-annotation-code{padding-right:0}code.sourceCode .code-annotation-anchor{z-index:100;position:relative;float:right;background-color:rgba(0,0,0,0)}input[type=checkbox]{margin-right:.5ch}:root{--mermaid-bg-color: #fff;--mermaid-edge-color: #6c757d;--mermaid-node-fg-color: #222;--mermaid-fg-color: #222;--mermaid-fg-color--lighter: #3c3c3c;--mermaid-fg-color--lightest: #555555;--mermaid-font-family: Lato;--mermaid-label-bg-color: #fff;--mermaid-label-fg-color: #2c3e50;--mermaid-node-bg-color: rgba(44, 62, 80, 0.1);--mermaid-node-fg-color: #222}@media print{:root{font-size:11pt}#quarto-sidebar,#TOC,.nav-page{display:none}.page-columns .content{grid-column-start:page-start}.fixed-top{position:relative}.panel-caption,.figure-caption,figcaption{color:#666}}.code-copy-button{position:absolute;top:0;right:0;border:0;margin-top:5px;margin-right:5px;background-color:rgba(0,0,0,0);z-index:3}.code-copy-button:focus{outline:none}.code-copy-button-tooltip{font-size:.75em}.code-copy-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.code-copy-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.code-copy-button-checked:hover>.bi::before{background-image:url('data:image/svg+xml,')}main ol ol,main ul ul,main ol ul,main ul ol{margin-bottom:1em}ul>li:not(:has(>p))>ul,ol>li:not(:has(>p))>ul,ul>li:not(:has(>p))>ol,ol>li:not(:has(>p))>ol{margin-bottom:0}ul>li:not(:has(>p))>ul>li:has(>p),ol>li:not(:has(>p))>ul>li:has(>p),ul>li:not(:has(>p))>ol>li:has(>p),ol>li:not(:has(>p))>ol>li:has(>p){margin-top:1rem}body{margin:0}main.page-columns>header>h1.title,main.page-columns>header>.title.h1{margin-bottom:0}@media(min-width: 992px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] 35px [page-end-inset page-end] 5fr [screen-end-inset] 1.5em}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 3em [body-end] 50px [body-end-outset] minmax(0px, 250px) [page-end-inset] minmax(50px, 100px) [page-end] 1fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 175px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 175px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(25px, 50px) [page-start-inset] minmax(50px, 150px) [body-start-outset] minmax(25px, 50px) [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 100px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 50px [page-start-inset] minmax(50px, 150px) [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(450px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 50px [page-start-inset] minmax(50px, 150px) [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(450px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 150px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(25px, 50px) [page-start-inset] minmax(50px, 150px) [body-start-outset] minmax(25px, 50px) [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 991.98px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(1250px - 3em)) [body-content-end body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 145px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 145px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1.5em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 767.98px){body .page-columns,body.fullcontent:not(.floating):not(.docked) .page-columns,body.slimcontent:not(.floating):not(.docked) .page-columns,body.docked .page-columns,body.docked.slimcontent .page-columns,body.docked.fullcontent .page-columns,body.floating .page-columns,body.floating.slimcontent .page-columns,body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}nav[role=doc-toc]{display:none}}body,.page-row-navigation{grid-template-rows:[page-top] max-content [contents-top] max-content [contents-bottom] max-content [page-bottom]}.page-rows-contents{grid-template-rows:[content-top] minmax(max-content, 1fr) [content-bottom] minmax(60px, max-content) [page-bottom]}.page-full{grid-column:screen-start/screen-end !important}.page-columns>*{grid-column:body-content-start/body-content-end}.page-columns.column-page>*{grid-column:page-start/page-end}.page-columns.column-page-left .page-columns.page-full>*,.page-columns.column-page-left>*{grid-column:page-start/body-content-end}.page-columns.column-page-right .page-columns.page-full>*,.page-columns.column-page-right>*{grid-column:body-content-start/page-end}.page-rows{grid-auto-rows:auto}.header{grid-column:screen-start/screen-end;grid-row:page-top/contents-top}#quarto-content{padding:0;grid-column:screen-start/screen-end;grid-row:contents-top/contents-bottom}body.floating .sidebar.sidebar-navigation{grid-column:page-start/body-start;grid-row:content-top/page-bottom}body.docked .sidebar.sidebar-navigation{grid-column:screen-start/body-start;grid-row:content-top/page-bottom}.sidebar.toc-left{grid-column:page-start/body-start;grid-row:content-top/page-bottom}.sidebar.margin-sidebar{grid-column:body-end/page-end;grid-row:content-top/page-bottom}.page-columns .content{grid-column:body-content-start/body-content-end;grid-row:content-top/content-bottom;align-content:flex-start}.page-columns .page-navigation{grid-column:body-content-start/body-content-end;grid-row:content-bottom/page-bottom}.page-columns .footer{grid-column:screen-start/screen-end;grid-row:contents-bottom/page-bottom}.page-columns .column-body{grid-column:body-content-start/body-content-end}.page-columns .column-body-fullbleed{grid-column:body-start/body-end}.page-columns .column-body-outset{grid-column:body-start-outset/body-end-outset;z-index:998;opacity:.999}.page-columns .column-body-outset table{background:#fff}.page-columns .column-body-outset-left{grid-column:body-start-outset/body-content-end;z-index:998;opacity:.999}.page-columns .column-body-outset-left table{background:#fff}.page-columns .column-body-outset-right{grid-column:body-content-start/body-end-outset;z-index:998;opacity:.999}.page-columns .column-body-outset-right table{background:#fff}.page-columns .column-page{grid-column:page-start/page-end;z-index:998;opacity:.999}.page-columns .column-page table{background:#fff}.page-columns .column-page-inset{grid-column:page-start-inset/page-end-inset;z-index:998;opacity:.999}.page-columns .column-page-inset table{background:#fff}.page-columns .column-page-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-page-inset-left table{background:#fff}.page-columns .column-page-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;opacity:.999}.page-columns .column-page-inset-right figcaption table{background:#fff}.page-columns .column-page-left{grid-column:page-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-page-left table{background:#fff}.page-columns .column-page-right{grid-column:body-content-start/page-end;z-index:998;opacity:.999}.page-columns .column-page-right figcaption table{background:#fff}#quarto-content.page-columns #quarto-margin-sidebar,#quarto-content.page-columns #quarto-sidebar{z-index:1}@media(max-width: 991.98px){#quarto-content.page-columns #quarto-margin-sidebar.collapse,#quarto-content.page-columns #quarto-sidebar.collapse,#quarto-content.page-columns #quarto-margin-sidebar.collapsing,#quarto-content.page-columns #quarto-sidebar.collapsing{z-index:1055}}#quarto-content.page-columns main.column-page,#quarto-content.page-columns main.column-page-right,#quarto-content.page-columns main.column-page-left{z-index:0}.page-columns .column-screen-inset{grid-column:screen-start-inset/screen-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:screen-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/screen-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:screen-start/screen-end;z-index:998;opacity:.999}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:screen-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/screen-end;z-index:998;opacity:.999}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:screen-start/screen-end;padding:1em;background:#ecf0f1;z-index:998;opacity:.999;margin-bottom:1em}.zindex-content{z-index:998;opacity:.999}.zindex-modal{z-index:1055;opacity:.999}.zindex-over-content{z-index:999;opacity:.999}img.img-fluid.column-screen,img.img-fluid.column-screen-inset-shaded,img.img-fluid.column-screen-inset,img.img-fluid.column-screen-inset-left,img.img-fluid.column-screen-inset-right,img.img-fluid.column-screen-left,img.img-fluid.column-screen-right{width:100%}@media(min-width: 992px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-end/page-end !important;z-index:998}.column-sidebar{grid-column:page-start/body-start !important;z-index:998}.column-leftmargin{grid-column:screen-start-inset/body-start !important;z-index:998}.no-row-height{height:1em;overflow:visible}}@media(max-width: 991.98px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-end/page-end !important;z-index:998}.no-row-height{height:1em;overflow:visible}.page-columns.page-full{overflow:visible}.page-columns.toc-left .margin-caption,.page-columns.toc-left div.aside,.page-columns.toc-left aside:not(.footnotes):not(.sidebar),.page-columns.toc-left .column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;opacity:.999}.page-columns.toc-left .no-row-height{height:initial;overflow:initial}}@media(max-width: 767.98px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;opacity:.999}.no-row-height{height:initial;overflow:initial}#quarto-margin-sidebar{display:none}#quarto-sidebar-toc-left{display:none}.hidden-sm{display:none}}.panel-grid{display:grid;grid-template-rows:repeat(1, 1fr);grid-template-columns:repeat(24, 1fr);gap:1em}.panel-grid .g-col-1{grid-column:auto/span 1}.panel-grid .g-col-2{grid-column:auto/span 2}.panel-grid .g-col-3{grid-column:auto/span 3}.panel-grid .g-col-4{grid-column:auto/span 4}.panel-grid .g-col-5{grid-column:auto/span 5}.panel-grid .g-col-6{grid-column:auto/span 6}.panel-grid .g-col-7{grid-column:auto/span 7}.panel-grid .g-col-8{grid-column:auto/span 8}.panel-grid .g-col-9{grid-column:auto/span 9}.panel-grid .g-col-10{grid-column:auto/span 10}.panel-grid .g-col-11{grid-column:auto/span 11}.panel-grid .g-col-12{grid-column:auto/span 12}.panel-grid .g-col-13{grid-column:auto/span 13}.panel-grid .g-col-14{grid-column:auto/span 14}.panel-grid .g-col-15{grid-column:auto/span 15}.panel-grid .g-col-16{grid-column:auto/span 16}.panel-grid .g-col-17{grid-column:auto/span 17}.panel-grid .g-col-18{grid-column:auto/span 18}.panel-grid .g-col-19{grid-column:auto/span 19}.panel-grid .g-col-20{grid-column:auto/span 20}.panel-grid .g-col-21{grid-column:auto/span 21}.panel-grid .g-col-22{grid-column:auto/span 22}.panel-grid .g-col-23{grid-column:auto/span 23}.panel-grid .g-col-24{grid-column:auto/span 24}.panel-grid .g-start-1{grid-column-start:1}.panel-grid .g-start-2{grid-column-start:2}.panel-grid .g-start-3{grid-column-start:3}.panel-grid .g-start-4{grid-column-start:4}.panel-grid .g-start-5{grid-column-start:5}.panel-grid .g-start-6{grid-column-start:6}.panel-grid .g-start-7{grid-column-start:7}.panel-grid .g-start-8{grid-column-start:8}.panel-grid .g-start-9{grid-column-start:9}.panel-grid .g-start-10{grid-column-start:10}.panel-grid .g-start-11{grid-column-start:11}.panel-grid .g-start-12{grid-column-start:12}.panel-grid .g-start-13{grid-column-start:13}.panel-grid .g-start-14{grid-column-start:14}.panel-grid .g-start-15{grid-column-start:15}.panel-grid .g-start-16{grid-column-start:16}.panel-grid .g-start-17{grid-column-start:17}.panel-grid .g-start-18{grid-column-start:18}.panel-grid .g-start-19{grid-column-start:19}.panel-grid .g-start-20{grid-column-start:20}.panel-grid .g-start-21{grid-column-start:21}.panel-grid .g-start-22{grid-column-start:22}.panel-grid .g-start-23{grid-column-start:23}@media(min-width: 576px){.panel-grid .g-col-sm-1{grid-column:auto/span 1}.panel-grid .g-col-sm-2{grid-column:auto/span 2}.panel-grid .g-col-sm-3{grid-column:auto/span 3}.panel-grid .g-col-sm-4{grid-column:auto/span 4}.panel-grid .g-col-sm-5{grid-column:auto/span 5}.panel-grid .g-col-sm-6{grid-column:auto/span 6}.panel-grid .g-col-sm-7{grid-column:auto/span 7}.panel-grid .g-col-sm-8{grid-column:auto/span 8}.panel-grid .g-col-sm-9{grid-column:auto/span 9}.panel-grid .g-col-sm-10{grid-column:auto/span 10}.panel-grid .g-col-sm-11{grid-column:auto/span 11}.panel-grid .g-col-sm-12{grid-column:auto/span 12}.panel-grid .g-col-sm-13{grid-column:auto/span 13}.panel-grid .g-col-sm-14{grid-column:auto/span 14}.panel-grid .g-col-sm-15{grid-column:auto/span 15}.panel-grid .g-col-sm-16{grid-column:auto/span 16}.panel-grid .g-col-sm-17{grid-column:auto/span 17}.panel-grid .g-col-sm-18{grid-column:auto/span 18}.panel-grid .g-col-sm-19{grid-column:auto/span 19}.panel-grid .g-col-sm-20{grid-column:auto/span 20}.panel-grid .g-col-sm-21{grid-column:auto/span 21}.panel-grid .g-col-sm-22{grid-column:auto/span 22}.panel-grid .g-col-sm-23{grid-column:auto/span 23}.panel-grid .g-col-sm-24{grid-column:auto/span 24}.panel-grid .g-start-sm-1{grid-column-start:1}.panel-grid .g-start-sm-2{grid-column-start:2}.panel-grid .g-start-sm-3{grid-column-start:3}.panel-grid .g-start-sm-4{grid-column-start:4}.panel-grid .g-start-sm-5{grid-column-start:5}.panel-grid .g-start-sm-6{grid-column-start:6}.panel-grid .g-start-sm-7{grid-column-start:7}.panel-grid .g-start-sm-8{grid-column-start:8}.panel-grid .g-start-sm-9{grid-column-start:9}.panel-grid .g-start-sm-10{grid-column-start:10}.panel-grid .g-start-sm-11{grid-column-start:11}.panel-grid .g-start-sm-12{grid-column-start:12}.panel-grid .g-start-sm-13{grid-column-start:13}.panel-grid .g-start-sm-14{grid-column-start:14}.panel-grid .g-start-sm-15{grid-column-start:15}.panel-grid .g-start-sm-16{grid-column-start:16}.panel-grid .g-start-sm-17{grid-column-start:17}.panel-grid .g-start-sm-18{grid-column-start:18}.panel-grid .g-start-sm-19{grid-column-start:19}.panel-grid .g-start-sm-20{grid-column-start:20}.panel-grid .g-start-sm-21{grid-column-start:21}.panel-grid .g-start-sm-22{grid-column-start:22}.panel-grid .g-start-sm-23{grid-column-start:23}}@media(min-width: 768px){.panel-grid .g-col-md-1{grid-column:auto/span 1}.panel-grid .g-col-md-2{grid-column:auto/span 2}.panel-grid .g-col-md-3{grid-column:auto/span 3}.panel-grid .g-col-md-4{grid-column:auto/span 4}.panel-grid .g-col-md-5{grid-column:auto/span 5}.panel-grid .g-col-md-6{grid-column:auto/span 6}.panel-grid .g-col-md-7{grid-column:auto/span 7}.panel-grid .g-col-md-8{grid-column:auto/span 8}.panel-grid .g-col-md-9{grid-column:auto/span 9}.panel-grid .g-col-md-10{grid-column:auto/span 10}.panel-grid .g-col-md-11{grid-column:auto/span 11}.panel-grid .g-col-md-12{grid-column:auto/span 12}.panel-grid .g-col-md-13{grid-column:auto/span 13}.panel-grid .g-col-md-14{grid-column:auto/span 14}.panel-grid .g-col-md-15{grid-column:auto/span 15}.panel-grid .g-col-md-16{grid-column:auto/span 16}.panel-grid .g-col-md-17{grid-column:auto/span 17}.panel-grid .g-col-md-18{grid-column:auto/span 18}.panel-grid .g-col-md-19{grid-column:auto/span 19}.panel-grid .g-col-md-20{grid-column:auto/span 20}.panel-grid .g-col-md-21{grid-column:auto/span 21}.panel-grid .g-col-md-22{grid-column:auto/span 22}.panel-grid .g-col-md-23{grid-column:auto/span 23}.panel-grid .g-col-md-24{grid-column:auto/span 24}.panel-grid .g-start-md-1{grid-column-start:1}.panel-grid .g-start-md-2{grid-column-start:2}.panel-grid .g-start-md-3{grid-column-start:3}.panel-grid .g-start-md-4{grid-column-start:4}.panel-grid .g-start-md-5{grid-column-start:5}.panel-grid .g-start-md-6{grid-column-start:6}.panel-grid .g-start-md-7{grid-column-start:7}.panel-grid .g-start-md-8{grid-column-start:8}.panel-grid .g-start-md-9{grid-column-start:9}.panel-grid .g-start-md-10{grid-column-start:10}.panel-grid .g-start-md-11{grid-column-start:11}.panel-grid .g-start-md-12{grid-column-start:12}.panel-grid .g-start-md-13{grid-column-start:13}.panel-grid .g-start-md-14{grid-column-start:14}.panel-grid .g-start-md-15{grid-column-start:15}.panel-grid .g-start-md-16{grid-column-start:16}.panel-grid .g-start-md-17{grid-column-start:17}.panel-grid .g-start-md-18{grid-column-start:18}.panel-grid .g-start-md-19{grid-column-start:19}.panel-grid .g-start-md-20{grid-column-start:20}.panel-grid .g-start-md-21{grid-column-start:21}.panel-grid .g-start-md-22{grid-column-start:22}.panel-grid .g-start-md-23{grid-column-start:23}}@media(min-width: 992px){.panel-grid .g-col-lg-1{grid-column:auto/span 1}.panel-grid .g-col-lg-2{grid-column:auto/span 2}.panel-grid .g-col-lg-3{grid-column:auto/span 3}.panel-grid .g-col-lg-4{grid-column:auto/span 4}.panel-grid .g-col-lg-5{grid-column:auto/span 5}.panel-grid .g-col-lg-6{grid-column:auto/span 6}.panel-grid .g-col-lg-7{grid-column:auto/span 7}.panel-grid .g-col-lg-8{grid-column:auto/span 8}.panel-grid .g-col-lg-9{grid-column:auto/span 9}.panel-grid .g-col-lg-10{grid-column:auto/span 10}.panel-grid .g-col-lg-11{grid-column:auto/span 11}.panel-grid .g-col-lg-12{grid-column:auto/span 12}.panel-grid .g-col-lg-13{grid-column:auto/span 13}.panel-grid .g-col-lg-14{grid-column:auto/span 14}.panel-grid .g-col-lg-15{grid-column:auto/span 15}.panel-grid .g-col-lg-16{grid-column:auto/span 16}.panel-grid .g-col-lg-17{grid-column:auto/span 17}.panel-grid .g-col-lg-18{grid-column:auto/span 18}.panel-grid .g-col-lg-19{grid-column:auto/span 19}.panel-grid .g-col-lg-20{grid-column:auto/span 20}.panel-grid .g-col-lg-21{grid-column:auto/span 21}.panel-grid .g-col-lg-22{grid-column:auto/span 22}.panel-grid .g-col-lg-23{grid-column:auto/span 23}.panel-grid .g-col-lg-24{grid-column:auto/span 24}.panel-grid .g-start-lg-1{grid-column-start:1}.panel-grid .g-start-lg-2{grid-column-start:2}.panel-grid .g-start-lg-3{grid-column-start:3}.panel-grid .g-start-lg-4{grid-column-start:4}.panel-grid .g-start-lg-5{grid-column-start:5}.panel-grid .g-start-lg-6{grid-column-start:6}.panel-grid .g-start-lg-7{grid-column-start:7}.panel-grid .g-start-lg-8{grid-column-start:8}.panel-grid .g-start-lg-9{grid-column-start:9}.panel-grid .g-start-lg-10{grid-column-start:10}.panel-grid .g-start-lg-11{grid-column-start:11}.panel-grid .g-start-lg-12{grid-column-start:12}.panel-grid .g-start-lg-13{grid-column-start:13}.panel-grid .g-start-lg-14{grid-column-start:14}.panel-grid .g-start-lg-15{grid-column-start:15}.panel-grid .g-start-lg-16{grid-column-start:16}.panel-grid .g-start-lg-17{grid-column-start:17}.panel-grid .g-start-lg-18{grid-column-start:18}.panel-grid .g-start-lg-19{grid-column-start:19}.panel-grid .g-start-lg-20{grid-column-start:20}.panel-grid .g-start-lg-21{grid-column-start:21}.panel-grid .g-start-lg-22{grid-column-start:22}.panel-grid .g-start-lg-23{grid-column-start:23}}@media(min-width: 1200px){.panel-grid .g-col-xl-1{grid-column:auto/span 1}.panel-grid .g-col-xl-2{grid-column:auto/span 2}.panel-grid .g-col-xl-3{grid-column:auto/span 3}.panel-grid .g-col-xl-4{grid-column:auto/span 4}.panel-grid .g-col-xl-5{grid-column:auto/span 5}.panel-grid .g-col-xl-6{grid-column:auto/span 6}.panel-grid .g-col-xl-7{grid-column:auto/span 7}.panel-grid .g-col-xl-8{grid-column:auto/span 8}.panel-grid .g-col-xl-9{grid-column:auto/span 9}.panel-grid .g-col-xl-10{grid-column:auto/span 10}.panel-grid .g-col-xl-11{grid-column:auto/span 11}.panel-grid .g-col-xl-12{grid-column:auto/span 12}.panel-grid .g-col-xl-13{grid-column:auto/span 13}.panel-grid .g-col-xl-14{grid-column:auto/span 14}.panel-grid .g-col-xl-15{grid-column:auto/span 15}.panel-grid .g-col-xl-16{grid-column:auto/span 16}.panel-grid .g-col-xl-17{grid-column:auto/span 17}.panel-grid .g-col-xl-18{grid-column:auto/span 18}.panel-grid .g-col-xl-19{grid-column:auto/span 19}.panel-grid .g-col-xl-20{grid-column:auto/span 20}.panel-grid .g-col-xl-21{grid-column:auto/span 21}.panel-grid .g-col-xl-22{grid-column:auto/span 22}.panel-grid .g-col-xl-23{grid-column:auto/span 23}.panel-grid .g-col-xl-24{grid-column:auto/span 24}.panel-grid .g-start-xl-1{grid-column-start:1}.panel-grid .g-start-xl-2{grid-column-start:2}.panel-grid .g-start-xl-3{grid-column-start:3}.panel-grid .g-start-xl-4{grid-column-start:4}.panel-grid .g-start-xl-5{grid-column-start:5}.panel-grid .g-start-xl-6{grid-column-start:6}.panel-grid .g-start-xl-7{grid-column-start:7}.panel-grid .g-start-xl-8{grid-column-start:8}.panel-grid .g-start-xl-9{grid-column-start:9}.panel-grid .g-start-xl-10{grid-column-start:10}.panel-grid .g-start-xl-11{grid-column-start:11}.panel-grid .g-start-xl-12{grid-column-start:12}.panel-grid .g-start-xl-13{grid-column-start:13}.panel-grid .g-start-xl-14{grid-column-start:14}.panel-grid .g-start-xl-15{grid-column-start:15}.panel-grid .g-start-xl-16{grid-column-start:16}.panel-grid .g-start-xl-17{grid-column-start:17}.panel-grid .g-start-xl-18{grid-column-start:18}.panel-grid .g-start-xl-19{grid-column-start:19}.panel-grid .g-start-xl-20{grid-column-start:20}.panel-grid .g-start-xl-21{grid-column-start:21}.panel-grid .g-start-xl-22{grid-column-start:22}.panel-grid .g-start-xl-23{grid-column-start:23}}@media(min-width: 1400px){.panel-grid .g-col-xxl-1{grid-column:auto/span 1}.panel-grid .g-col-xxl-2{grid-column:auto/span 2}.panel-grid .g-col-xxl-3{grid-column:auto/span 3}.panel-grid .g-col-xxl-4{grid-column:auto/span 4}.panel-grid .g-col-xxl-5{grid-column:auto/span 5}.panel-grid .g-col-xxl-6{grid-column:auto/span 6}.panel-grid .g-col-xxl-7{grid-column:auto/span 7}.panel-grid .g-col-xxl-8{grid-column:auto/span 8}.panel-grid .g-col-xxl-9{grid-column:auto/span 9}.panel-grid .g-col-xxl-10{grid-column:auto/span 10}.panel-grid .g-col-xxl-11{grid-column:auto/span 11}.panel-grid .g-col-xxl-12{grid-column:auto/span 12}.panel-grid .g-col-xxl-13{grid-column:auto/span 13}.panel-grid .g-col-xxl-14{grid-column:auto/span 14}.panel-grid .g-col-xxl-15{grid-column:auto/span 15}.panel-grid .g-col-xxl-16{grid-column:auto/span 16}.panel-grid .g-col-xxl-17{grid-column:auto/span 17}.panel-grid .g-col-xxl-18{grid-column:auto/span 18}.panel-grid .g-col-xxl-19{grid-column:auto/span 19}.panel-grid .g-col-xxl-20{grid-column:auto/span 20}.panel-grid .g-col-xxl-21{grid-column:auto/span 21}.panel-grid .g-col-xxl-22{grid-column:auto/span 22}.panel-grid .g-col-xxl-23{grid-column:auto/span 23}.panel-grid .g-col-xxl-24{grid-column:auto/span 24}.panel-grid .g-start-xxl-1{grid-column-start:1}.panel-grid .g-start-xxl-2{grid-column-start:2}.panel-grid .g-start-xxl-3{grid-column-start:3}.panel-grid .g-start-xxl-4{grid-column-start:4}.panel-grid .g-start-xxl-5{grid-column-start:5}.panel-grid .g-start-xxl-6{grid-column-start:6}.panel-grid .g-start-xxl-7{grid-column-start:7}.panel-grid .g-start-xxl-8{grid-column-start:8}.panel-grid .g-start-xxl-9{grid-column-start:9}.panel-grid .g-start-xxl-10{grid-column-start:10}.panel-grid .g-start-xxl-11{grid-column-start:11}.panel-grid .g-start-xxl-12{grid-column-start:12}.panel-grid .g-start-xxl-13{grid-column-start:13}.panel-grid .g-start-xxl-14{grid-column-start:14}.panel-grid .g-start-xxl-15{grid-column-start:15}.panel-grid .g-start-xxl-16{grid-column-start:16}.panel-grid .g-start-xxl-17{grid-column-start:17}.panel-grid .g-start-xxl-18{grid-column-start:18}.panel-grid .g-start-xxl-19{grid-column-start:19}.panel-grid .g-start-xxl-20{grid-column-start:20}.panel-grid .g-start-xxl-21{grid-column-start:21}.panel-grid .g-start-xxl-22{grid-column-start:22}.panel-grid .g-start-xxl-23{grid-column-start:23}}main{margin-top:1em;margin-bottom:1em}h1,.h1,h2,.h2{color:inherit;margin-top:2rem;margin-bottom:1rem;font-weight:600}h1.title,.title.h1{margin-top:0}main.content>section:first-of-type>h2:first-child,main.content>section:first-of-type>.h2:first-child{margin-top:0}h2,.h2{border-bottom:1px solid #dee2e6;padding-bottom:.5rem}h3,.h3{font-weight:600}h3,.h3,h4,.h4{opacity:.9;margin-top:1.5rem}h5,.h5,h6,.h6{opacity:.9}.header-section-number{color:#626262}.nav-link.active .header-section-number{color:inherit}mark,.mark{padding:0em}.panel-caption,.figure-caption,.subfigure-caption,.table-caption,figcaption,caption{font-size:.9rem;color:#626262}.quarto-layout-cell[data-ref-parent] caption{color:#626262}.column-margin figcaption,.margin-caption,div.aside,aside,.column-margin{color:#626262;font-size:.825rem}.panel-caption.margin-caption{text-align:inherit}.column-margin.column-container p{margin-bottom:0}.column-margin.column-container>*:not(.collapse):first-child{padding-bottom:.5em;display:block}.column-margin.column-container>*:not(.collapse):not(:first-child){padding-top:.5em;padding-bottom:.5em;display:block}.column-margin.column-container>*.collapse:not(.show){display:none}@media(min-width: 768px){.column-margin.column-container .callout-margin-content:first-child{margin-top:4.5em}.column-margin.column-container .callout-margin-content-simple:first-child{margin-top:3.5em}}.margin-caption>*{padding-top:.5em;padding-bottom:.5em}@media(max-width: 767.98px){.quarto-layout-row{flex-direction:column}}.nav-tabs .nav-item{margin-top:1px;cursor:pointer}.tab-content{margin-top:0px;border-left:#ecf0f1 1px solid;border-right:#ecf0f1 1px solid;border-bottom:#ecf0f1 1px solid;margin-left:0;padding:1em;margin-bottom:1em}@media(max-width: 767.98px){.layout-sidebar{margin-left:0;margin-right:0}}.panel-sidebar,.panel-sidebar .form-control,.panel-input,.panel-input .form-control,.selectize-dropdown{font-size:.9rem}.panel-sidebar .form-control,.panel-input .form-control{padding-top:.1rem}.tab-pane div.sourceCode{margin-top:0px}.tab-pane>p{padding-top:0}.tab-pane>p:nth-child(1){padding-top:0}.tab-pane>p:last-child{margin-bottom:0}.tab-pane>pre:last-child{margin-bottom:0}.tab-content>.tab-pane:not(.active){display:none !important}div.sourceCode{background-color:rgba(236,240,241,.65);border:1px solid rgba(236,240,241,.65);border-radius:.25rem}pre.sourceCode{background-color:rgba(0,0,0,0)}pre.sourceCode{border:none;font-size:.875em;overflow:visible !important;padding:.4em}.callout pre.sourceCode{padding-left:0}div.sourceCode{overflow-y:hidden}.callout div.sourceCode{margin-left:initial}.blockquote{font-size:inherit;padding-left:1rem;padding-right:1.5rem;color:#626262}.blockquote h1:first-child,.blockquote .h1:first-child,.blockquote h2:first-child,.blockquote .h2:first-child,.blockquote h3:first-child,.blockquote .h3:first-child,.blockquote h4:first-child,.blockquote .h4:first-child,.blockquote h5:first-child,.blockquote .h5:first-child{margin-top:0}pre{background-color:initial;padding:initial;border:initial}p pre code:not(.sourceCode),li pre code:not(.sourceCode),pre code:not(.sourceCode){background-color:initial}p code:not(.sourceCode),li code:not(.sourceCode),td code:not(.sourceCode){background-color:#f8f9fa;padding:.2em}nav p code:not(.sourceCode),nav li code:not(.sourceCode),nav td code:not(.sourceCode){background-color:rgba(0,0,0,0);padding:0}td code:not(.sourceCode){white-space:pre-wrap}#quarto-embedded-source-code-modal>.modal-dialog{max-width:1000px;padding-left:1.75rem;padding-right:1.75rem}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body{padding:0}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body div.sourceCode{margin:0;padding:.2rem .2rem;border-radius:0px;border:none}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-header{padding:.7rem}.code-tools-button{font-size:1rem;padding:.15rem .15rem;margin-left:5px;color:#6c757d;background-color:rgba(0,0,0,0);transition:initial;cursor:pointer}.code-tools-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.sidebar{will-change:top;transition:top 200ms linear;position:sticky;overflow-y:auto;padding-top:1.2em;max-height:100vh}.sidebar.toc-left,.sidebar.margin-sidebar{top:0px;padding-top:1em}.sidebar.quarto-banner-title-block-sidebar>*{padding-top:1.65em}figure .quarto-notebook-link{margin-top:.5em}.quarto-notebook-link{font-size:.75em;color:#6c757d;margin-bottom:1em;text-decoration:none;display:block}.quarto-notebook-link:hover{text-decoration:underline;color:#5e7ca1}.quarto-notebook-link::before{display:inline-block;height:.75rem;width:.75rem;margin-bottom:0em;margin-right:.25em;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:.75rem .75rem}.toc-actions i.bi,.quarto-code-links i.bi,.quarto-other-links i.bi,.quarto-alternate-notebooks i.bi,.quarto-alternate-formats i.bi{margin-right:.4em;font-size:.8rem}.quarto-other-links-text-target .quarto-code-links i.bi,.quarto-other-links-text-target .quarto-other-links i.bi{margin-right:.2em}.quarto-other-formats-text-target .quarto-alternate-formats i.bi{margin-right:.1em}.toc-actions i.bi.empty,.quarto-code-links i.bi.empty,.quarto-other-links i.bi.empty,.quarto-alternate-notebooks i.bi.empty,.quarto-alternate-formats i.bi.empty{padding-left:1em}.quarto-notebook h2,.quarto-notebook .h2{border-bottom:none}.quarto-notebook .cell-container{display:flex}.quarto-notebook .cell-container .cell{flex-grow:4}.quarto-notebook .cell-container .cell-decorator{padding-top:1.5em;padding-right:1em;text-align:right}.quarto-notebook .cell-container.code-fold .cell-decorator{padding-top:3em}.quarto-notebook .cell-code code{white-space:pre-wrap}.quarto-notebook .cell .cell-output-stderr pre code,.quarto-notebook .cell .cell-output-stdout pre code{white-space:pre-wrap;overflow-wrap:anywhere}.toc-actions,.quarto-alternate-formats,.quarto-other-links,.quarto-code-links,.quarto-alternate-notebooks{padding-left:0em}.sidebar .toc-actions a,.sidebar .quarto-alternate-formats a,.sidebar .quarto-other-links a,.sidebar .quarto-code-links a,.sidebar .quarto-alternate-notebooks a,.sidebar nav[role=doc-toc] a{text-decoration:none}.sidebar .toc-actions a:hover,.sidebar .quarto-other-links a:hover,.sidebar .quarto-code-links a:hover,.sidebar .quarto-alternate-formats a:hover,.sidebar .quarto-alternate-notebooks a:hover{color:#5e7ca1}.sidebar .toc-actions h2,.sidebar .toc-actions .h2,.sidebar .quarto-code-links h2,.sidebar .quarto-code-links .h2,.sidebar .quarto-other-links h2,.sidebar .quarto-other-links .h2,.sidebar .quarto-alternate-notebooks h2,.sidebar .quarto-alternate-notebooks .h2,.sidebar .quarto-alternate-formats h2,.sidebar .quarto-alternate-formats .h2,.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-weight:500;margin-bottom:.2rem;margin-top:.3rem;font-family:inherit;border-bottom:0;padding-bottom:0;padding-top:0px}.sidebar .toc-actions>h2,.sidebar .toc-actions>.h2,.sidebar .quarto-code-links>h2,.sidebar .quarto-code-links>.h2,.sidebar .quarto-other-links>h2,.sidebar .quarto-other-links>.h2,.sidebar .quarto-alternate-notebooks>h2,.sidebar .quarto-alternate-notebooks>.h2,.sidebar .quarto-alternate-formats>h2,.sidebar .quarto-alternate-formats>.h2{font-size:.8rem}.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-size:.875rem}.sidebar nav[role=doc-toc]>ul a{border-left:1px solid #ecf0f1;padding-left:.6rem}.sidebar .toc-actions h2>ul a,.sidebar .toc-actions .h2>ul a,.sidebar .quarto-code-links h2>ul a,.sidebar .quarto-code-links .h2>ul a,.sidebar .quarto-other-links h2>ul a,.sidebar .quarto-other-links .h2>ul a,.sidebar .quarto-alternate-notebooks h2>ul a,.sidebar .quarto-alternate-notebooks .h2>ul a,.sidebar .quarto-alternate-formats h2>ul a,.sidebar .quarto-alternate-formats .h2>ul a{border-left:none;padding-left:.6rem}.sidebar .toc-actions ul a:empty,.sidebar .quarto-code-links ul a:empty,.sidebar .quarto-other-links ul a:empty,.sidebar .quarto-alternate-notebooks ul a:empty,.sidebar .quarto-alternate-formats ul a:empty,.sidebar nav[role=doc-toc]>ul a:empty{display:none}.sidebar .toc-actions ul,.sidebar .quarto-code-links ul,.sidebar .quarto-other-links ul,.sidebar .quarto-alternate-notebooks ul,.sidebar .quarto-alternate-formats ul{padding-left:0;list-style:none}.sidebar nav[role=doc-toc] ul{list-style:none;padding-left:0;list-style:none}.sidebar nav[role=doc-toc]>ul{margin-left:.45em}.quarto-margin-sidebar nav[role=doc-toc]{padding-left:.5em}.sidebar .toc-actions>ul,.sidebar .quarto-code-links>ul,.sidebar .quarto-other-links>ul,.sidebar .quarto-alternate-notebooks>ul,.sidebar .quarto-alternate-formats>ul{font-size:.8rem}.sidebar nav[role=doc-toc]>ul{font-size:.875rem}.sidebar .toc-actions ul li a,.sidebar .quarto-code-links ul li a,.sidebar .quarto-other-links ul li a,.sidebar .quarto-alternate-notebooks ul li a,.sidebar .quarto-alternate-formats ul li a,.sidebar nav[role=doc-toc]>ul li a{line-height:1.1rem;padding-bottom:.2rem;padding-top:.2rem;color:inherit}.sidebar nav[role=doc-toc] ul>li>ul>li>a{padding-left:1.2em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>a{padding-left:2.4em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>a{padding-left:3.6em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:4.8em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:6em}.sidebar nav[role=doc-toc] ul>li>a.active,.sidebar nav[role=doc-toc] ul>li>ul>li>a.active{border-left:1px solid #222;color:#222 !important}.sidebar nav[role=doc-toc] ul>li>a:hover,.sidebar nav[role=doc-toc] ul>li>ul>li>a:hover{color:#222 !important}kbd,.kbd{color:#222;background-color:#f8f9fa;border:1px solid;border-radius:5px;border-color:#dee2e6}.quarto-appendix-contents div.hanging-indent{margin-left:0em}.quarto-appendix-contents div.hanging-indent div.csl-entry{margin-left:1em;text-indent:-1em}.citation a,.footnote-ref{text-decoration:none}.footnotes ol{padding-left:1em}.tippy-content>*{margin-bottom:.7em}.tippy-content>*:last-child{margin-bottom:0}.callout{margin-top:1.25rem;margin-bottom:1.25rem;border-radius:.25rem;overflow-wrap:break-word}.callout .callout-title-container{overflow-wrap:anywhere}.callout.callout-style-simple{padding:.4em .7em;border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout.callout-style-default{border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout .callout-body-container{flex-grow:1}.callout.callout-style-simple .callout-body{font-size:.9rem;font-weight:400}.callout.callout-style-default .callout-body{font-size:.9rem;font-weight:400}.callout:not(.no-icon).callout-titled.callout-style-simple .callout-body{padding-left:1.6em}.callout.callout-titled>.callout-header{padding-top:.2em;margin-bottom:-0.2em}.callout.callout-style-simple>div.callout-header{border-bottom:none;font-size:.9rem;font-weight:600;opacity:75%}.callout.callout-style-default>div.callout-header{border-bottom:none;font-weight:600;opacity:85%;font-size:.9rem;padding-left:.5em;padding-right:.5em}.callout.callout-style-default .callout-body{padding-left:.5em;padding-right:.5em}.callout.callout-style-default .callout-body>:first-child{padding-top:.5rem;margin-top:0}.callout>div.callout-header[data-bs-toggle=collapse]{cursor:pointer}.callout.callout-style-default .callout-header[aria-expanded=false],.callout.callout-style-default .callout-header[aria-expanded=true]{padding-top:0px;margin-bottom:0px;align-items:center}.callout.callout-titled .callout-body>:last-child:not(.sourceCode),.callout.callout-titled .callout-body>div>:last-child:not(.sourceCode){padding-bottom:.5rem;margin-bottom:0}.callout:not(.callout-titled) .callout-body>:first-child,.callout:not(.callout-titled) .callout-body>div>:first-child{margin-top:.25rem}.callout:not(.callout-titled) .callout-body>:last-child,.callout:not(.callout-titled) .callout-body>div>:last-child{margin-bottom:.2rem}.callout.callout-style-simple .callout-icon::before,.callout.callout-style-simple .callout-toggle::before{height:1rem;width:1rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.callout.callout-style-default .callout-icon::before,.callout.callout-style-default .callout-toggle::before{height:.9rem;width:.9rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:.9rem .9rem}.callout.callout-style-default .callout-toggle::before{margin-top:5px}.callout .callout-btn-toggle .callout-toggle::before{transition:transform .2s linear}.callout .callout-header[aria-expanded=false] .callout-toggle::before{transform:rotate(-90deg)}.callout .callout-header[aria-expanded=true] .callout-toggle::before{transform:none}.callout.callout-style-simple:not(.no-icon) div.callout-icon-container{padding-top:.2em;padding-right:.55em}.callout.callout-style-default:not(.no-icon) div.callout-icon-container{padding-top:.1em;padding-right:.35em}.callout.callout-style-default:not(.no-icon) div.callout-title-container{margin-top:-1px}.callout.callout-style-default.callout-caution:not(.no-icon) div.callout-icon-container{padding-top:.3em;padding-right:.35em}.callout>.callout-body>.callout-icon-container>.no-icon,.callout>.callout-header>.callout-icon-container>.no-icon{display:none}div.callout.callout{border-left-color:#6c757d}div.callout.callout-style-default>.callout-header{background-color:#6c757d}div.callout-note.callout{border-left-color:#2c3e50}div.callout-note.callout-style-default>.callout-header{background-color:#eaecee}div.callout-note:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-tip.callout{border-left-color:#18bc9c}div.callout-tip.callout-style-default>.callout-header{background-color:#e8f8f5}div.callout-tip:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-warning.callout{border-left-color:#f39c12}div.callout-warning.callout-style-default>.callout-header{background-color:#fef5e7}div.callout-warning:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-caution.callout{border-left-color:#fd7e14}div.callout-caution.callout-style-default>.callout-header{background-color:#fff2e8}div.callout-caution:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-important.callout{border-left-color:#e74c3c}div.callout-important.callout-style-default>.callout-header{background-color:#fdedec}div.callout-important:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important .callout-toggle::before{background-image:url('data:image/svg+xml,')}.quarto-toggle-container{display:flex;align-items:center}.quarto-reader-toggle .bi::before,.quarto-color-scheme-toggle .bi::before{display:inline-block;height:1rem;width:1rem;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.sidebar-navigation{padding-left:20px}.navbar{background-color:#ececec;color:#222}.navbar .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.quarto-sidebar-toggle{border-color:#dee2e6;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;border-style:solid;border-width:1px;overflow:hidden;border-top-width:0px;padding-top:0px !important}.quarto-sidebar-toggle-title{cursor:pointer;padding-bottom:2px;margin-left:.25em;text-align:center;font-weight:400;font-size:.775em}#quarto-content .quarto-sidebar-toggle{background:#fafafa}#quarto-content .quarto-sidebar-toggle-title{color:#222}.quarto-sidebar-toggle-icon{color:#dee2e6;margin-right:.5em;float:right;transition:transform .2s ease}.quarto-sidebar-toggle-icon::before{padding-top:5px}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-icon{transform:rotate(-180deg)}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-title{border-bottom:solid #dee2e6 1px}.quarto-sidebar-toggle-contents{background-color:#fff;padding-right:10px;padding-left:10px;margin-top:0px !important;transition:max-height .5s ease}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-contents{padding-top:1em;padding-bottom:10px}@media(max-width: 767.98px){.sidebar-menu-container{padding-bottom:5em}}.quarto-sidebar-toggle:not(.expanded) .quarto-sidebar-toggle-contents{padding-top:0px !important;padding-bottom:0px}nav[role=doc-toc]{z-index:1020}#quarto-sidebar>*,nav[role=doc-toc]>*{transition:opacity .1s ease,border .1s ease}#quarto-sidebar.slow>*,nav[role=doc-toc].slow>*{transition:opacity .4s ease,border .4s ease}.quarto-color-scheme-toggle:not(.alternate).top-right .bi::before{background-image:url('data:image/svg+xml,')}.quarto-color-scheme-toggle.alternate.top-right .bi::before{background-image:url('data:image/svg+xml,')}#quarto-appendix.default{border-top:1px solid #dee2e6}#quarto-appendix.default{background-color:#fff;padding-top:1.5em;margin-top:2em;z-index:998}#quarto-appendix.default .quarto-appendix-heading{margin-top:0;line-height:1.4em;font-weight:600;opacity:.9;border-bottom:none;margin-bottom:0}#quarto-appendix.default .footnotes ol,#quarto-appendix.default .footnotes ol li>p:last-of-type,#quarto-appendix.default .quarto-appendix-contents>p:last-of-type{margin-bottom:0}#quarto-appendix.default .footnotes ol{margin-left:.5em}#quarto-appendix.default .quarto-appendix-secondary-label{margin-bottom:.4em}#quarto-appendix.default .quarto-appendix-bibtex{font-size:.7em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-bibtex code.sourceCode{white-space:pre-wrap}#quarto-appendix.default .quarto-appendix-citeas{font-size:.9em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-heading{font-size:1em !important}#quarto-appendix.default *[role=doc-endnotes]>ol,#quarto-appendix.default .quarto-appendix-contents>*:not(h2):not(.h2){font-size:.9em}#quarto-appendix.default section{padding-bottom:1.5em}#quarto-appendix.default section *[role=doc-endnotes],#quarto-appendix.default section>*:not(a){opacity:.9;word-wrap:break-word}.btn.btn-quarto,div.cell-output-display .btn-quarto{--bs-btn-color: #fefefe;--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fefefe;--bs-btn-hover-bg: #828a91;--bs-btn-hover-border-color: #7b838a;--bs-btn-focus-shadow-rgb: 130, 138, 144;--bs-btn-active-color: #fff;--bs-btn-active-bg: #899197;--bs-btn-active-border-color: #7b838a;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}nav.quarto-secondary-nav.color-navbar{background-color:#ececec;color:#222}nav.quarto-secondary-nav.color-navbar h1,nav.quarto-secondary-nav.color-navbar .h1,nav.quarto-secondary-nav.color-navbar .quarto-btn-toggle{color:#222}@media(max-width: 991.98px){body.nav-sidebar .quarto-title-banner{margin-bottom:0;padding-bottom:1em}body.nav-sidebar #title-block-header{margin-block-end:0}}p.subtitle{margin-top:.25em;margin-bottom:.5em}code a:any-link{color:inherit;text-decoration-color:#6c757d}/*! light */div.observablehq table thead tr th{background-color:var(--bs-body-bg)}input,button,select,optgroup,textarea{background-color:var(--bs-body-bg)}.code-annotated .code-copy-button{margin-right:1.25em;margin-top:0;padding-bottom:0;padding-top:3px}.code-annotation-gutter-bg{background-color:#fff}.code-annotation-gutter{background-color:rgba(236,240,241,.65)}.code-annotation-gutter,.code-annotation-gutter-bg{height:100%;width:calc(20px + .5em);position:absolute;top:0;right:0}dl.code-annotation-container-grid dt{margin-right:1em;margin-top:.25rem}dl.code-annotation-container-grid dt{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;color:#3c3c3c;border:solid #3c3c3c 1px;border-radius:50%;height:22px;width:22px;line-height:22px;font-size:11px;text-align:center;vertical-align:middle;text-decoration:none}dl.code-annotation-container-grid dt[data-target-cell]{cursor:pointer}dl.code-annotation-container-grid dt[data-target-cell].code-annotation-active{color:#fff;border:solid #aaa 1px;background-color:#aaa}pre.code-annotation-code{padding-top:0;padding-bottom:0}pre.code-annotation-code code{z-index:3}#code-annotation-line-highlight-gutter{width:100%;border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}#code-annotation-line-highlight{margin-left:-4em;width:calc(100% + 4em);border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}code.sourceCode .code-annotation-anchor.code-annotation-active{background-color:var(--quarto-hl-normal-color, #aaaaaa);border:solid var(--quarto-hl-normal-color, #aaaaaa) 1px;color:#ecf0f1;font-weight:bolder}code.sourceCode .code-annotation-anchor{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;color:var(--quarto-hl-co-color);border:solid var(--quarto-hl-co-color) 1px;border-radius:50%;height:18px;width:18px;font-size:9px;margin-top:2px}code.sourceCode button.code-annotation-anchor{padding:2px;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none}code.sourceCode a.code-annotation-anchor{line-height:18px;text-align:center;vertical-align:middle;cursor:default;text-decoration:none}@media print{.page-columns .column-screen-inset{grid-column:page-start-inset/page-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:page-start/page-end;z-index:998;opacity:.999}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:page-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/page-end;z-index:998;opacity:.999}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:page-start-inset/page-end-inset;padding:1em;background:#ecf0f1;z-index:998;opacity:.999;margin-bottom:1em}}.quarto-video{margin-bottom:1em}.table{border-top:1px solid #d5d5d5;border-bottom:1px solid #d5d5d5}.table>thead{border-top-width:0;border-bottom:1px solid #a2a2a2}.table a{word-break:break-word}.table>:not(caption)>*>*{background-color:unset;color:unset}#quarto-document-content .crosstalk-input .checkbox input[type=checkbox],#quarto-document-content .crosstalk-input .checkbox-inline input[type=checkbox]{position:unset;margin-top:unset;margin-left:unset}#quarto-document-content .row{margin-left:unset;margin-right:unset}.quarto-xref{white-space:nowrap}#quarto-draft-alert{margin-top:0px;margin-bottom:0px;padding:.3em;text-align:center;font-size:.9em}#quarto-draft-alert i{margin-right:.3em}a.external:after{content:"";background-image:url('data:image/svg+xml,');background-size:contain;background-repeat:no-repeat;background-position:center center;margin-left:.2em;padding-right:.75em}div.sourceCode code a.external:after{content:none}a.external:after:hover{cursor:pointer}.quarto-ext-icon{display:inline-block;font-size:.75em;padding-left:.3em}.code-with-filename .code-with-filename-file{margin-bottom:0;padding-bottom:2px;padding-top:2px;padding-left:.7em;border:var(--quarto-border-width) solid var(--quarto-border-color);border-radius:var(--quarto-border-radius);border-bottom:0;border-bottom-left-radius:0%;border-bottom-right-radius:0%}.code-with-filename div.sourceCode,.reveal .code-with-filename div.sourceCode{margin-top:0;border-top-left-radius:0%;border-top-right-radius:0%}.code-with-filename .code-with-filename-file pre{margin-bottom:0}.code-with-filename .code-with-filename-file{background-color:rgba(219,219,219,.8)}.quarto-dark .code-with-filename .code-with-filename-file{background-color:#555}.code-with-filename .code-with-filename-file strong{font-weight:400}.quarto-title-banner{margin-bottom:1em;color:#222;background:#ececec}.quarto-title-banner a{color:#222}.quarto-title-banner h1,.quarto-title-banner .h1,.quarto-title-banner h2,.quarto-title-banner .h2{color:#222}.quarto-title-banner .code-tools-button{color:#555}.quarto-title-banner .code-tools-button:hover{color:#222}.quarto-title-banner .code-tools-button>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .quarto-title .title{font-weight:600}.quarto-title-banner .quarto-categories{margin-top:.75em}@media(min-width: 992px){.quarto-title-banner{padding-top:2.5em;padding-bottom:2.5em}}@media(max-width: 991.98px){.quarto-title-banner{padding-top:1em;padding-bottom:1em}}@media(max-width: 767.98px){body.hypothesis-enabled #title-block-header>*{padding-right:20px}}main.quarto-banner-title-block>section:first-child>h2,main.quarto-banner-title-block>section:first-child>.h2,main.quarto-banner-title-block>section:first-child>h3,main.quarto-banner-title-block>section:first-child>.h3,main.quarto-banner-title-block>section:first-child>h4,main.quarto-banner-title-block>section:first-child>.h4{margin-top:0}.quarto-title .quarto-categories{display:flex;flex-wrap:wrap;row-gap:.5em;column-gap:.4em;padding-bottom:.5em;margin-top:.75em}.quarto-title .quarto-categories .quarto-category{padding:.25em .75em;font-size:.65em;text-transform:uppercase;border:solid 1px;border-radius:.25rem;opacity:.6}.quarto-title .quarto-categories .quarto-category a{color:inherit}.quarto-title-meta-container{display:grid;grid-template-columns:1fr auto}.quarto-title-meta-column-end{display:flex;flex-direction:column;padding-left:1em}.quarto-title-meta-column-end a .bi{margin-right:.3em}#title-block-header.quarto-title-block.default .quarto-title-meta{display:grid;grid-template-columns:minmax(max-content, 1fr) 1fr;grid-column-gap:1em}#title-block-header.quarto-title-block.default .quarto-title .title{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-author-orcid img{margin-top:-0.2em;height:.8em;width:.8em}#title-block-header.quarto-title-block.default .quarto-title-author-email{opacity:.7}#title-block-header.quarto-title-block.default .quarto-description p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p,#title-block-header.quarto-title-block.default .quarto-title-authors p,#title-block-header.quarto-title-block.default .quarto-title-affiliations p{margin-bottom:.1em}#title-block-header.quarto-title-block.default .quarto-title-meta-heading{text-transform:uppercase;margin-top:1em;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-contents{font-size:.9em}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p.affiliation:last-of-type{margin-bottom:.1em}#title-block-header.quarto-title-block.default p.affiliation{margin-bottom:.1em}#title-block-header.quarto-title-block.default .keywords,#title-block-header.quarto-title-block.default .description,#title-block-header.quarto-title-block.default .abstract{margin-top:0}#title-block-header.quarto-title-block.default .keywords>p,#title-block-header.quarto-title-block.default .description>p,#title-block-header.quarto-title-block.default .abstract>p{font-size:.9em}#title-block-header.quarto-title-block.default .keywords>p:last-of-type,#title-block-header.quarto-title-block.default .description>p:last-of-type,#title-block-header.quarto-title-block.default .abstract>p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .keywords .block-title,#title-block-header.quarto-title-block.default .description .block-title,#title-block-header.quarto-title-block.default .abstract .block-title{margin-top:1em;text-transform:uppercase;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-author{display:grid;grid-template-columns:minmax(max-content, 1fr) 1fr;grid-column-gap:1em}.quarto-title-tools-only{display:flex;justify-content:right}.bg-primary .navbar-nav .show>.nav-link,.bg-primary .navbar-nav .nav-link.active,.bg-primary .navbar-nav .nav-link:hover,.bg-primary .navbar-nav .nav-link:focus{color:#18bc9c !important}.nav-tabs .nav-link.active,.nav-tabs .nav-link.active:focus,.nav-tabs .nav-link.active:hover,.nav-tabs .nav-item.open .nav-link,.nav-tabs .nav-item.open .nav-link:focus,.nav-tabs .nav-item.open .nav-link:hover{color:#2c3e50}.pagination a:hover{text-decoration:none}.badge.bg-light{color:#7b8a8b}.alert{color:#fff;border:none}.alert a,.alert .alert-link{color:#fff;text-decoration:underline}.alert-default{background-color:#6c757d}.alert-primary{background-color:#2c3e50}.alert-secondary{background-color:#6c757d}.alert-success{background-color:#18bc9c}.alert-info{background-color:#3498db}.alert-warning{background-color:#f39c12}.alert-danger{background-color:#e74c3c}.alert-light{background-color:#ecf0f1}.alert-dark{background-color:#7b8a8b}.alert-light,.alert-light a,.alert-light .alert-link{color:#222}.modal .btn-close,.toast .btn-close,.offcanvas .btn-close{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e")} diff --git a/docs/site_libs/bootstrap/bootstrap.min.js b/docs/site_libs/bootstrap/bootstrap.min.js new file mode 100644 index 000000000..e8f21f703 --- /dev/null +++ b/docs/site_libs/bootstrap/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),s=t=>{t.dispatchEvent(new Event(i))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,m=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},g=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,_=(t,e,n=!0)=>{if(!n)return void g(t);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),g(t))};e.addEventListener(i,a),setTimeout((()=>{r||s(e)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=I(t);return C.has(o)||(o=t),[n,s,o]}function S(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return P(s,{delegateTarget:r}),n.oneOff&&N.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return P(n,{delegateTarget:t}),i.oneOff&&N.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function D(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function $(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&D(t,e,i,r.callable,r.delegationSelector)}function I(t){return t=t.replace(y,""),T[t]||t}const N={on(t,e,i,n){S(t,e,i,n,!1)},one(t,e,i,n){S(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))$(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(w,"");a&&!e.includes(s)||D(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;D(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==I(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=P(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function P(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function M(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function j(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const F={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${j(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${j(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=M(t.dataset[n])}return e},getDataAttribute:(t,e)=>M(t.getAttribute(`data-bs-${j(e)}`))};class H{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?F.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?F.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],r=o(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(r))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${r}" but expected type "${s}".`)}var i}}class W extends H{constructor(t,i){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),N.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.1"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const B=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return n(e)},z={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))},getSelectorFromElement(t){const e=B(t);return e&&z.findOne(e)?e:null},getElementFromSelector(t){const e=B(t);return e?z.findOne(e):null},getMultipleElementsFromSelector(t){const e=B(t);return e?z.find(e):[]}},R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;N.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const s=z.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},q=".bs.alert",V=`close${q}`,K=`closed${q}`;class Q extends W{static get NAME(){return"alert"}close(){if(N.trigger(this._element,V).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),N.trigger(this._element,K),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Q.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(Q,"close"),m(Q);const X='[data-bs-toggle="button"]';class Y extends W{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=Y.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}N.on(document,"click.bs.button.data-api",X,(t=>{t.preventDefault();const e=t.target.closest(X);Y.getOrCreateInstance(e).toggle()})),m(Y);const U=".bs.swipe",G=`touchstart${U}`,J=`touchmove${U}`,Z=`touchend${U}`,tt=`pointerdown${U}`,et=`pointerup${U}`,it={endCallback:null,leftCallback:null,rightCallback:null},nt={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class st extends H{constructor(t,e){super(),this._element=t,t&&st.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return it}static get DefaultType(){return nt}static get NAME(){return"swipe"}dispose(){N.off(this._element,U)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),g(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&g(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(N.on(this._element,tt,(t=>this._start(t))),N.on(this._element,et,(t=>this._end(t))),this._element.classList.add("pointer-event")):(N.on(this._element,G,(t=>this._start(t))),N.on(this._element,J,(t=>this._move(t))),N.on(this._element,Z,(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const ot=".bs.carousel",rt=".data-api",at="next",lt="prev",ct="left",ht="right",dt=`slide${ot}`,ut=`slid${ot}`,ft=`keydown${ot}`,pt=`mouseenter${ot}`,mt=`mouseleave${ot}`,gt=`dragstart${ot}`,_t=`load${ot}${rt}`,bt=`click${ot}${rt}`,vt="carousel",yt="active",wt=".active",At=".carousel-item",Et=wt+At,Tt={ArrowLeft:ht,ArrowRight:ct},Ct={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Ot={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class xt extends W{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=z.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===vt&&this.cycle()}static get Default(){return Ct}static get DefaultType(){return Ot}static get NAME(){return"carousel"}next(){this._slide(at)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(lt)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?N.one(this._element,ut,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void N.one(this._element,ut,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?at:lt;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&N.on(this._element,ft,(t=>this._keydown(t))),"hover"===this._config.pause&&(N.on(this._element,pt,(()=>this.pause())),N.on(this._element,mt,(()=>this._maybeEnableCycle()))),this._config.touch&&st.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of z.find(".carousel-item img",this._element))N.on(t,gt,(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(ct)),rightCallback:()=>this._slide(this._directionToOrder(ht)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new st(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=Tt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=z.findOne(wt,this._indicatorsElement);e.classList.remove(yt),e.removeAttribute("aria-current");const i=z.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(yt),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===at,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>N.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(dt).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(yt),i.classList.remove(yt,c,l),this._isSliding=!1,r(ut)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return z.findOne(Et,this._element)}_getItems(){return z.find(At,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===ct?lt:at:t===ct?at:lt}_orderToDirection(t){return p()?t===lt?ct:ht:t===lt?ht:ct}static jQueryInterface(t){return this.each((function(){const e=xt.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}N.on(document,bt,"[data-bs-slide], [data-bs-slide-to]",(function(t){const e=z.getElementFromSelector(this);if(!e||!e.classList.contains(vt))return;t.preventDefault();const i=xt.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===F.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),N.on(window,_t,(()=>{const t=z.find('[data-bs-ride="carousel"]');for(const e of t)xt.getOrCreateInstance(e)})),m(xt);const kt=".bs.collapse",Lt=`show${kt}`,St=`shown${kt}`,Dt=`hide${kt}`,$t=`hidden${kt}`,It=`click${kt}.data-api`,Nt="show",Pt="collapse",Mt="collapsing",jt=`:scope .${Pt} .${Pt}`,Ft='[data-bs-toggle="collapse"]',Ht={parent:null,toggle:!0},Wt={parent:"(null|element)",toggle:"boolean"};class Bt extends W{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=z.find(Ft);for(const t of i){const e=z.getSelectorFromElement(t),i=z.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return Ht}static get DefaultType(){return Wt}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>Bt.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(N.trigger(this._element,Lt).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(Pt),this._element.classList.add(Mt),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt,Nt),this._element.style[e]="",N.trigger(this._element,St)}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(N.trigger(this._element,Dt).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(Mt),this._element.classList.remove(Pt,Nt);for(const t of this._triggerArray){const e=z.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt),N.trigger(this._element,$t)}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(Nt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(Ft);for(const e of t){const t=z.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=z.find(jt,this._config.parent);return z.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=Bt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}N.on(document,It,Ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of z.getMultipleElementsFromSelector(this))Bt.getOrCreateInstance(t,{toggle:!1}).toggle()})),m(Bt);var zt="top",Rt="bottom",qt="right",Vt="left",Kt="auto",Qt=[zt,Rt,qt,Vt],Xt="start",Yt="end",Ut="clippingParents",Gt="viewport",Jt="popper",Zt="reference",te=Qt.reduce((function(t,e){return t.concat([e+"-"+Xt,e+"-"+Yt])}),[]),ee=[].concat(Qt,[Kt]).reduce((function(t,e){return t.concat([e,e+"-"+Xt,e+"-"+Yt])}),[]),ie="beforeRead",ne="read",se="afterRead",oe="beforeMain",re="main",ae="afterMain",le="beforeWrite",ce="write",he="afterWrite",de=[ie,ne,se,oe,re,ae,le,ce,he];function ue(t){return t?(t.nodeName||"").toLowerCase():null}function fe(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function pe(t){return t instanceof fe(t).Element||t instanceof Element}function me(t){return t instanceof fe(t).HTMLElement||t instanceof HTMLElement}function ge(t){return"undefined"!=typeof ShadowRoot&&(t instanceof fe(t).ShadowRoot||t instanceof ShadowRoot)}const _e={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];me(s)&&ue(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});me(n)&&ue(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function be(t){return t.split("-")[0]}var ve=Math.max,ye=Math.min,we=Math.round;function Ae(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Ee(){return!/^((?!chrome|android).)*safari/i.test(Ae())}function Te(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&me(t)&&(s=t.offsetWidth>0&&we(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&we(n.height)/t.offsetHeight||1);var r=(pe(t)?fe(t):window).visualViewport,a=!Ee()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Ce(t){var e=Te(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Oe(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&ge(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function xe(t){return fe(t).getComputedStyle(t)}function ke(t){return["table","td","th"].indexOf(ue(t))>=0}function Le(t){return((pe(t)?t.ownerDocument:t.document)||window.document).documentElement}function Se(t){return"html"===ue(t)?t:t.assignedSlot||t.parentNode||(ge(t)?t.host:null)||Le(t)}function De(t){return me(t)&&"fixed"!==xe(t).position?t.offsetParent:null}function $e(t){for(var e=fe(t),i=De(t);i&&ke(i)&&"static"===xe(i).position;)i=De(i);return i&&("html"===ue(i)||"body"===ue(i)&&"static"===xe(i).position)?e:i||function(t){var e=/firefox/i.test(Ae());if(/Trident/i.test(Ae())&&me(t)&&"fixed"===xe(t).position)return null;var i=Se(t);for(ge(i)&&(i=i.host);me(i)&&["html","body"].indexOf(ue(i))<0;){var n=xe(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function Ie(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Ne(t,e,i){return ve(t,ye(e,i))}function Pe(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function Me(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const je={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=be(i.placement),l=Ie(a),c=[Vt,qt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return Pe("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:Me(t,Qt))}(s.padding,i),d=Ce(o),u="y"===l?zt:Vt,f="y"===l?Rt:qt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=$e(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=Ne(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Oe(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Fe(t){return t.split("-")[1]}var He={top:"auto",right:"auto",bottom:"auto",left:"auto"};function We(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=Vt,y=zt,w=window;if(c){var A=$e(i),E="clientHeight",T="clientWidth";A===fe(i)&&"static"!==xe(A=Le(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===zt||(s===Vt||s===qt)&&o===Yt)&&(y=Rt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==Vt&&(s!==zt&&s!==Rt||o!==Yt)||(v=qt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&He),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:we(i*s)/s||0,y:we(n*s)/s||0}}({x:f,y:m},fe(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const Be={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:be(e.placement),variation:Fe(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,We(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,We(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var ze={passive:!0};const Re={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=fe(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,ze)})),a&&l.addEventListener("resize",i.update,ze),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,ze)})),a&&l.removeEventListener("resize",i.update,ze)}},data:{}};var qe={left:"right",right:"left",bottom:"top",top:"bottom"};function Ve(t){return t.replace(/left|right|bottom|top/g,(function(t){return qe[t]}))}var Ke={start:"end",end:"start"};function Qe(t){return t.replace(/start|end/g,(function(t){return Ke[t]}))}function Xe(t){var e=fe(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ye(t){return Te(Le(t)).left+Xe(t).scrollLeft}function Ue(t){var e=xe(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ge(t){return["html","body","#document"].indexOf(ue(t))>=0?t.ownerDocument.body:me(t)&&Ue(t)?t:Ge(Se(t))}function Je(t,e){var i;void 0===e&&(e=[]);var n=Ge(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=fe(n),r=s?[o].concat(o.visualViewport||[],Ue(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Je(Se(r)))}function Ze(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function ti(t,e,i){return e===Gt?Ze(function(t,e){var i=fe(t),n=Le(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Ee();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Ye(t),y:l}}(t,i)):pe(e)?function(t,e){var i=Te(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Ze(function(t){var e,i=Le(t),n=Xe(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ve(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ve(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ye(t),l=-n.scrollTop;return"rtl"===xe(s||i).direction&&(a+=ve(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Le(t)))}function ei(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?be(s):null,r=s?Fe(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case zt:e={x:a,y:i.y-n.height};break;case Rt:e={x:a,y:i.y+i.height};break;case qt:e={x:i.x+i.width,y:l};break;case Vt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?Ie(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case Xt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Yt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ii(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Ut:a,c=i.rootBoundary,h=void 0===c?Gt:c,d=i.elementContext,u=void 0===d?Jt:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=Pe("number"!=typeof g?g:Me(g,Qt)),b=u===Jt?Zt:Jt,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Je(Se(t)),i=["absolute","fixed"].indexOf(xe(t).position)>=0&&me(t)?$e(t):t;return pe(i)?e.filter((function(t){return pe(t)&&Oe(t,i)&&"body"!==ue(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=ti(t,i,n);return e.top=ve(s.top,e.top),e.right=ye(s.right,e.right),e.bottom=ye(s.bottom,e.bottom),e.left=ve(s.left,e.left),e}),ti(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(pe(y)?y:y.contextElement||Le(t.elements.popper),l,h,r),A=Te(t.elements.reference),E=ei({reference:A,element:v,strategy:"absolute",placement:s}),T=Ze(Object.assign({},v,E)),C=u===Jt?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Jt&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[qt,Rt].indexOf(t)>=0?1:-1,i=[zt,Rt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function ni(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?ee:l,h=Fe(n),d=h?a?te:te.filter((function(t){return Fe(t)===h})):Qt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ii(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[be(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const si={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=be(g),b=l||(_!==g&&p?function(t){if(be(t)===Kt)return[];var e=Ve(t);return[Qe(t),e,Qe(e)]}(g):[Ve(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(be(i)===Kt?ni(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=ii(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),$=L?k?qt:Vt:k?Rt:zt;y[S]>w[S]&&($=Ve($));var I=Ve($),N=[];if(o&&N.push(D[x]<=0),a&&N.push(D[$]<=0,D[I]<=0),N.every((function(t){return t}))){T=O,E=!1;break}A.set(O,N)}if(E)for(var P=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==P(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function oi(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function ri(t){return[zt,qt,Rt,Vt].some((function(e){return t[e]>=0}))}const ai={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ii(e,{elementContext:"reference"}),a=ii(e,{altBoundary:!0}),l=oi(r,n),c=oi(a,s,o),h=ri(l),d=ri(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},li={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=ee.reduce((function(t,i){return t[i]=function(t,e,i){var n=be(t),s=[Vt,zt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Vt,qt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},ci={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=ei({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},hi={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ii(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=be(e.placement),b=Fe(e.placement),v=!b,y=Ie(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?zt:Vt,D="y"===y?Rt:qt,$="y"===y?"height":"width",I=A[y],N=I+g[S],P=I-g[D],M=f?-T[$]/2:0,j=b===Xt?E[$]:T[$],F=b===Xt?-T[$]:-E[$],H=e.elements.arrow,W=f&&H?Ce(H):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=Ne(0,E[$],W[$]),V=v?E[$]/2-M-q-z-O.mainAxis:j-q-z-O.mainAxis,K=v?-E[$]/2+M+q+R+O.mainAxis:F+q+R+O.mainAxis,Q=e.elements.arrow&&$e(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=I+K-Y,G=Ne(f?ye(N,I+V-Y-X):N,I,f?ve(P,U):P);A[y]=G,k[y]=G-I}if(a){var J,Z="x"===y?zt:Vt,tt="x"===y?Rt:qt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[zt,Vt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=Ne(t,e,i);return n>i?i:n}(at,et,lt):Ne(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function di(t,e,i){void 0===i&&(i=!1);var n,s,o=me(e),r=me(e)&&function(t){var e=t.getBoundingClientRect(),i=we(e.width)/t.offsetWidth||1,n=we(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=Le(e),l=Te(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==ue(e)||Ue(a))&&(c=(n=e)!==fe(n)&&me(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:Xe(n)),me(e)?((h=Te(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Ye(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function ui(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var fi={placement:"bottom",modifiers:[],strategy:"absolute"};function pi(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(F.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...g(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Ti,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=z.find(Ni);for(const i of e){const e=qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Ei,Ti].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ii)?this:z.prev(this,Ii)[0]||z.next(this,Ii)[0]||z.findOne(Ii,t.delegateTarget.parentNode),o=qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}N.on(document,Si,Ii,qi.dataApiKeydownHandler),N.on(document,Si,Pi,qi.dataApiKeydownHandler),N.on(document,Li,qi.clearMenus),N.on(document,Di,qi.clearMenus),N.on(document,Li,Ii,(function(t){t.preventDefault(),qi.getOrCreateInstance(this).toggle()})),m(qi);const Vi="backdrop",Ki="show",Qi=`mousedown.bs.${Vi}`,Xi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Yi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Ui extends H{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Xi}static get DefaultType(){return Yi}static get NAME(){return Vi}show(t){if(!this._config.isVisible)return void g(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(Ki),this._emulateAnimation((()=>{g(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Ki),this._emulateAnimation((()=>{this.dispose(),g(t)}))):g(t)}dispose(){this._isAppended&&(N.off(this._element,Qi),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),N.on(t,Qi,(()=>{g(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const Gi=".bs.focustrap",Ji=`focusin${Gi}`,Zi=`keydown.tab${Gi}`,tn="backward",en={autofocus:!0,trapElement:null},nn={autofocus:"boolean",trapElement:"element"};class sn extends H{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return en}static get DefaultType(){return nn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),N.off(document,Gi),N.on(document,Ji,(t=>this._handleFocusin(t))),N.on(document,Zi,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,N.off(document,Gi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=z.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===tn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?tn:"forward")}}const on=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",rn=".sticky-top",an="padding-right",ln="margin-right";class cn{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,an,(e=>e+t)),this._setElementAttributes(on,an,(e=>e+t)),this._setElementAttributes(rn,ln,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,an),this._resetElementAttributes(on,an),this._resetElementAttributes(rn,ln)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&F.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=F.getDataAttribute(t,e);null!==i?(F.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of z.find(t,this._element))e(i)}}const hn=".bs.modal",dn=`hide${hn}`,un=`hidePrevented${hn}`,fn=`hidden${hn}`,pn=`show${hn}`,mn=`shown${hn}`,gn=`resize${hn}`,_n=`click.dismiss${hn}`,bn=`mousedown.dismiss${hn}`,vn=`keydown.dismiss${hn}`,yn=`click${hn}.data-api`,wn="modal-open",An="show",En="modal-static",Tn={backdrop:!0,focus:!0,keyboard:!0},Cn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class On extends W{constructor(t,e){super(t,e),this._dialog=z.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new cn,this._addEventListeners()}static get Default(){return Tn}static get DefaultType(){return Cn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||N.trigger(this._element,pn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(wn),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(N.trigger(this._element,dn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(An),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){N.off(window,hn),N.off(this._dialog,hn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Ui({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=z.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(An),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,N.trigger(this._element,mn,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){N.on(this._element,vn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),N.on(window,gn,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),N.on(this._element,bn,(t=>{N.one(this._element,_n,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(wn),this._resetAdjustments(),this._scrollBar.reset(),N.trigger(this._element,fn)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(N.trigger(this._element,un).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(En)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(En),this._queueCallback((()=>{this._element.classList.remove(En),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=On.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}N.on(document,yn,'[data-bs-toggle="modal"]',(function(t){const e=z.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),N.one(e,pn,(t=>{t.defaultPrevented||N.one(e,fn,(()=>{a(this)&&this.focus()}))}));const i=z.findOne(".modal.show");i&&On.getInstance(i).hide(),On.getOrCreateInstance(e).toggle(this)})),R(On),m(On);const xn=".bs.offcanvas",kn=".data-api",Ln=`load${xn}${kn}`,Sn="show",Dn="showing",$n="hiding",In=".offcanvas.show",Nn=`show${xn}`,Pn=`shown${xn}`,Mn=`hide${xn}`,jn=`hidePrevented${xn}`,Fn=`hidden${xn}`,Hn=`resize${xn}`,Wn=`click${xn}${kn}`,Bn=`keydown.dismiss${xn}`,zn={backdrop:!0,keyboard:!0,scroll:!1},Rn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class qn extends W{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return zn}static get DefaultType(){return Rn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||N.trigger(this._element,Nn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new cn).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Dn),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Sn),this._element.classList.remove(Dn),N.trigger(this._element,Pn,{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(N.trigger(this._element,Mn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add($n),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Sn,$n),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new cn).reset(),N.trigger(this._element,Fn)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Ui({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():N.trigger(this._element,jn)}:null})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_addEventListeners(){N.on(this._element,Bn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():N.trigger(this._element,jn))}))}static jQueryInterface(t){return this.each((function(){const e=qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}N.on(document,Wn,'[data-bs-toggle="offcanvas"]',(function(t){const e=z.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;N.one(e,Fn,(()=>{a(this)&&this.focus()}));const i=z.findOne(In);i&&i!==e&&qn.getInstance(i).hide(),qn.getOrCreateInstance(e).toggle(this)})),N.on(window,Ln,(()=>{for(const t of z.find(In))qn.getOrCreateInstance(t).show()})),N.on(window,Hn,(()=>{for(const t of z.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&qn.getOrCreateInstance(t).hide()})),R(qn),m(qn);const Vn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Kn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Qn=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Xn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Kn.has(i)||Boolean(Qn.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Yn={allowList:Vn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Un={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Gn={entry:"(string|element|function|null)",selector:"(string|element)"};class Jn extends H{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Yn}static get DefaultType(){return Un}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Gn)}_setContent(t,e,i){const n=z.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Xn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return g(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Zn=new Set(["sanitize","allowList","sanitizeFn"]),ts="fade",es="show",is=".modal",ns="hide.bs.modal",ss="hover",os="focus",rs={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},as={allowList:Vn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ls={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cs extends W{constructor(t,e){if(void 0===vi)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return as}static get DefaultType(){return ls}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),N.off(this._element.closest(is),ns,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=N.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),N.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.on(t,"mouseover",h);this._queueCallback((()=>{N.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!N.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger[os]=!1,this._activeTrigger[ss]=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),N.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ts,es),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ts),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Jn({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ts)}_isShown(){return this.tip&&this.tip.classList.contains(es)}_createPopper(t){const e=g(this._config.placement,[this,t,this._element]),i=rs[e.toUpperCase()];return bi(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return g(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...g(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)N.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===ss?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ss?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");N.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?os:ss]=!0,e._enter()})),N.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?os:ss]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},N.on(this._element.closest(is),ns,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=F.getDataAttributes(this._element);for(const t of Object.keys(e))Zn.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(cs);const hs={...cs.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},ds={...cs.DefaultType,content:"(null|string|element|function)"};class us extends cs{static get Default(){return hs}static get DefaultType(){return ds}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=us.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(us);const fs=".bs.scrollspy",ps=`activate${fs}`,ms=`click${fs}`,gs=`load${fs}.data-api`,_s="active",bs="[href]",vs=".nav-link",ys=`${vs}, .nav-item > ${vs}, .list-group-item`,ws={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},As={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Es extends W{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ws}static get DefaultType(){return As}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(N.off(this._config.target,ms),N.on(this._config.target,ms,bs,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=z.find(bs,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=z.findOne(decodeURI(e.hash),this._element);a(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(_s),this._activateParents(t),N.trigger(this._element,ps,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))z.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(_s);else for(const e of z.parents(t,".nav, .list-group"))for(const t of z.prev(e,ys))t.classList.add(_s)}_clearActiveClass(t){t.classList.remove(_s);const e=z.find(`${bs}.${_s}`,t);for(const t of e)t.classList.remove(_s)}static jQueryInterface(t){return this.each((function(){const e=Es.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(window,gs,(()=>{for(const t of z.find('[data-bs-spy="scroll"]'))Es.getOrCreateInstance(t)})),m(Es);const Ts=".bs.tab",Cs=`hide${Ts}`,Os=`hidden${Ts}`,xs=`show${Ts}`,ks=`shown${Ts}`,Ls=`click${Ts}`,Ss=`keydown${Ts}`,Ds=`load${Ts}`,$s="ArrowLeft",Is="ArrowRight",Ns="ArrowUp",Ps="ArrowDown",Ms="Home",js="End",Fs="active",Hs="fade",Ws="show",Bs=":not(.dropdown-toggle)",zs='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Rs=`.nav-link${Bs}, .list-group-item${Bs}, [role="tab"]${Bs}, ${zs}`,qs=`.${Fs}[data-bs-toggle="tab"], .${Fs}[data-bs-toggle="pill"], .${Fs}[data-bs-toggle="list"]`;class Vs extends W{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),N.on(this._element,Ss,(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?N.trigger(e,Cs,{relatedTarget:t}):null;N.trigger(t,xs,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Fs),this._activate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),N.trigger(t,ks,{relatedTarget:e})):t.classList.add(Ws)}),t,t.classList.contains(Hs)))}_deactivate(t,e){t&&(t.classList.remove(Fs),t.blur(),this._deactivate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),N.trigger(t,Os,{relatedTarget:e})):t.classList.remove(Ws)}),t,t.classList.contains(Hs)))}_keydown(t){if(![$s,Is,Ns,Ps,Ms,js].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter((t=>!l(t)));let i;if([Ms,js].includes(t.key))i=e[t.key===Ms?0:e.length-1];else{const n=[Is,Ps].includes(t.key);i=b(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Vs.getOrCreateInstance(i).show())}_getChildren(){return z.find(Rs,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=z.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=z.findOne(t,i);s&&s.classList.toggle(n,e)};n(".dropdown-toggle",Fs),n(".dropdown-menu",Ws),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Fs)}_getInnerElement(t){return t.matches(Rs)?t:z.findOne(Rs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=Vs.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(document,Ls,zs,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||Vs.getOrCreateInstance(this).show()})),N.on(window,Ds,(()=>{for(const t of z.find(qs))Vs.getOrCreateInstance(t)})),m(Vs);const Ks=".bs.toast",Qs=`mouseover${Ks}`,Xs=`mouseout${Ks}`,Ys=`focusin${Ks}`,Us=`focusout${Ks}`,Gs=`hide${Ks}`,Js=`hidden${Ks}`,Zs=`show${Ks}`,to=`shown${Ks}`,eo="hide",io="show",no="showing",so={animation:"boolean",autohide:"boolean",delay:"number"},oo={animation:!0,autohide:!0,delay:5e3};class ro extends W{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return oo}static get DefaultType(){return so}static get NAME(){return"toast"}show(){N.trigger(this._element,Zs).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(eo),d(this._element),this._element.classList.add(io,no),this._queueCallback((()=>{this._element.classList.remove(no),N.trigger(this._element,to),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(N.trigger(this._element,Gs).defaultPrevented||(this._element.classList.add(no),this._queueCallback((()=>{this._element.classList.add(eo),this._element.classList.remove(no,io),N.trigger(this._element,Js)}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(io),super.dispose()}isShown(){return this._element.classList.contains(io)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){N.on(this._element,Qs,(t=>this._onInteraction(t,!0))),N.on(this._element,Xs,(t=>this._onInteraction(t,!1))),N.on(this._element,Ys,(t=>this._onInteraction(t,!0))),N.on(this._element,Us,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=ro.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(ro),m(ro),{Alert:Q,Button:Y,Carousel:xt,Collapse:Bt,Dropdown:qi,Modal:On,Offcanvas:qn,Popover:us,ScrollSpy:Es,Tab:Vs,Toast:ro,Tooltip:cs}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/docs/site_libs/clipboard/clipboard.min.js b/docs/site_libs/clipboard/clipboard.min.js new file mode 100644 index 000000000..1103f811e --- /dev/null +++ b/docs/site_libs/clipboard/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1.container-fluid.crosstalk-bscols{margin-left:auto;margin-right:auto}.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column{display:inline-block;padding-right:12px;vertical-align:top}@media only screen and (max-width: 480px){.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column{display:block;padding-right:inherit}}.crosstalk-input{margin-bottom:15px}.crosstalk-input .control-label{margin-bottom:0;vertical-align:middle}.crosstalk-input input[type="checkbox"]{margin:4px 0 0;margin-top:1px;line-height:normal}.crosstalk-input .checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.crosstalk-input .checkbox>label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.crosstalk-input .checkbox input[type="checkbox"],.crosstalk-input .checkbox-inline input[type="checkbox"]{position:absolute;margin-top:2px;margin-left:-20px}.crosstalk-input .checkbox+.checkbox{margin-top:-5px}.crosstalk-input .checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.crosstalk-input .checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px} diff --git a/docs/site_libs/crosstalk-1.2.1/js/crosstalk.js b/docs/site_libs/crosstalk-1.2.1/js/crosstalk.js new file mode 100644 index 000000000..fd9eb53d2 --- /dev/null +++ b/docs/site_libs/crosstalk-1.2.1/js/crosstalk.js @@ -0,0 +1,1474 @@ +(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o b) { + return 1; + } +} + +/** + * @private + */ + +var FilterSet = function () { + function FilterSet() { + _classCallCheck(this, FilterSet); + + this.reset(); + } + + _createClass(FilterSet, [{ + key: "reset", + value: function reset() { + // Key: handle ID, Value: array of selected keys, or null + this._handles = {}; + // Key: key string, Value: count of handles that include it + this._keys = {}; + this._value = null; + this._activeHandles = 0; + } + }, { + key: "update", + value: function update(handleId, keys) { + if (keys !== null) { + keys = keys.slice(0); // clone before sorting + keys.sort(naturalComparator); + } + + var _diffSortedLists = (0, _util.diffSortedLists)(this._handles[handleId], keys), + added = _diffSortedLists.added, + removed = _diffSortedLists.removed; + + this._handles[handleId] = keys; + + for (var i = 0; i < added.length; i++) { + this._keys[added[i]] = (this._keys[added[i]] || 0) + 1; + } + for (var _i = 0; _i < removed.length; _i++) { + this._keys[removed[_i]]--; + } + + this._updateValue(keys); + } + + /** + * @param {string[]} keys Sorted array of strings that indicate + * a superset of possible keys. + * @private + */ + + }, { + key: "_updateValue", + value: function _updateValue() { + var keys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._allKeys; + + var handleCount = Object.keys(this._handles).length; + if (handleCount === 0) { + this._value = null; + } else { + this._value = []; + for (var i = 0; i < keys.length; i++) { + var count = this._keys[keys[i]]; + if (count === handleCount) { + this._value.push(keys[i]); + } + } + } + } + }, { + key: "clear", + value: function clear(handleId) { + if (typeof this._handles[handleId] === "undefined") { + return; + } + + var keys = this._handles[handleId]; + if (!keys) { + keys = []; + } + + for (var i = 0; i < keys.length; i++) { + this._keys[keys[i]]--; + } + delete this._handles[handleId]; + + this._updateValue(); + } + }, { + key: "value", + get: function get() { + return this._value; + } + }, { + key: "_allKeys", + get: function get() { + var allKeys = Object.keys(this._keys); + allKeys.sort(naturalComparator); + return allKeys; + } + }]); + + return FilterSet; +}(); + +exports.default = FilterSet; + +},{"./util":11}],4:[function(require,module,exports){ +(function (global){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +exports.default = group; + +var _var2 = require("./var"); + +var _var3 = _interopRequireDefault(_var2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +// Use a global so that multiple copies of crosstalk.js can be loaded and still +// have groups behave as singletons across all copies. +global.__crosstalk_groups = global.__crosstalk_groups || {}; +var groups = global.__crosstalk_groups; + +function group(groupName) { + if (groupName && typeof groupName === "string") { + if (!groups.hasOwnProperty(groupName)) { + groups[groupName] = new Group(groupName); + } + return groups[groupName]; + } else if ((typeof groupName === "undefined" ? "undefined" : _typeof(groupName)) === "object" && groupName._vars && groupName.var) { + // Appears to already be a group object + return groupName; + } else if (Array.isArray(groupName) && groupName.length == 1 && typeof groupName[0] === "string") { + return group(groupName[0]); + } else { + throw new Error("Invalid groupName argument"); + } +} + +var Group = function () { + function Group(name) { + _classCallCheck(this, Group); + + this.name = name; + this._vars = {}; + } + + _createClass(Group, [{ + key: "var", + value: function _var(name) { + if (!name || typeof name !== "string") { + throw new Error("Invalid var name"); + } + + if (!this._vars.hasOwnProperty(name)) this._vars[name] = new _var3.default(this, name); + return this._vars[name]; + } + }, { + key: "has", + value: function has(name) { + if (!name || typeof name !== "string") { + throw new Error("Invalid var name"); + } + + return this._vars.hasOwnProperty(name); + } + }]); + + return Group; +}(); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./var":12}],5:[function(require,module,exports){ +(function (global){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _group = require("./group"); + +var _group2 = _interopRequireDefault(_group); + +var _selection = require("./selection"); + +var _filter = require("./filter"); + +var _input = require("./input"); + +require("./input_selectize"); + +require("./input_checkboxgroup"); + +require("./input_slider"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var defaultGroup = (0, _group2.default)("default"); + +function var_(name) { + return defaultGroup.var(name); +} + +function has(name) { + return defaultGroup.has(name); +} + +if (global.Shiny) { + global.Shiny.addCustomMessageHandler("update-client-value", function (message) { + if (typeof message.group === "string") { + (0, _group2.default)(message.group).var(message.name).set(message.value); + } else { + var_(message.name).set(message.value); + } + }); +} + +var crosstalk = { + group: _group2.default, + var: var_, + has: has, + SelectionHandle: _selection.SelectionHandle, + FilterHandle: _filter.FilterHandle, + bind: _input.bind +}; + +/** + * @namespace crosstalk + */ +exports.default = crosstalk; + +global.crosstalk = crosstalk; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./filter":2,"./group":4,"./input":6,"./input_checkboxgroup":7,"./input_selectize":8,"./input_slider":9,"./selection":10}],6:[function(require,module,exports){ +(function (global){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.register = register; +exports.bind = bind; +var $ = global.jQuery; + +var bindings = {}; + +function register(reg) { + bindings[reg.className] = reg; + if (global.document && global.document.readyState !== "complete") { + $(function () { + bind(); + }); + } else if (global.document) { + setTimeout(bind, 100); + } +} + +function bind() { + Object.keys(bindings).forEach(function (className) { + var binding = bindings[className]; + $("." + binding.className).not(".crosstalk-input-bound").each(function (i, el) { + bindInstance(binding, el); + }); + }); +} + +// Escape jQuery identifier +function $escape(val) { + return val.replace(/([!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, "\\$1"); +} + +function bindEl(el) { + var $el = $(el); + Object.keys(bindings).forEach(function (className) { + if ($el.hasClass(className) && !$el.hasClass("crosstalk-input-bound")) { + var binding = bindings[className]; + bindInstance(binding, el); + } + }); +} + +function bindInstance(binding, el) { + var jsonEl = $(el).find("script[type='application/json'][data-for='" + $escape(el.id) + "']"); + var data = JSON.parse(jsonEl[0].innerText); + + var instance = binding.factory(el, data); + $(el).data("crosstalk-instance", instance); + $(el).addClass("crosstalk-input-bound"); +} + +if (global.Shiny) { + var inputBinding = new global.Shiny.InputBinding(); + var _$ = global.jQuery; + _$.extend(inputBinding, { + find: function find(scope) { + return _$(scope).find(".crosstalk-input"); + }, + initialize: function initialize(el) { + if (!_$(el).hasClass("crosstalk-input-bound")) { + bindEl(el); + } + }, + getId: function getId(el) { + return el.id; + }, + getValue: function getValue(el) {}, + setValue: function setValue(el, value) {}, + receiveMessage: function receiveMessage(el, data) {}, + subscribe: function subscribe(el, callback) { + _$(el).data("crosstalk-instance").resume(); + }, + unsubscribe: function unsubscribe(el) { + _$(el).data("crosstalk-instance").suspend(); + } + }); + global.Shiny.inputBindings.register(inputBinding, "crosstalk.inputBinding"); +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],7:[function(require,module,exports){ +(function (global){ +"use strict"; + +var _input = require("./input"); + +var input = _interopRequireWildcard(_input); + +var _filter = require("./filter"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var $ = global.jQuery; + +input.register({ + className: "crosstalk-input-checkboxgroup", + + factory: function factory(el, data) { + /* + * map: {"groupA": ["keyA", "keyB", ...], ...} + * group: "ct-groupname" + */ + var ctHandle = new _filter.FilterHandle(data.group); + + var lastKnownKeys = void 0; + var $el = $(el); + $el.on("change", "input[type='checkbox']", function () { + var checked = $el.find("input[type='checkbox']:checked"); + if (checked.length === 0) { + lastKnownKeys = null; + ctHandle.clear(); + } else { + var keys = {}; + checked.each(function () { + data.map[this.value].forEach(function (key) { + keys[key] = true; + }); + }); + var keyArray = Object.keys(keys); + keyArray.sort(); + lastKnownKeys = keyArray; + ctHandle.set(keyArray); + } + }); + + return { + suspend: function suspend() { + ctHandle.clear(); + }, + resume: function resume() { + if (lastKnownKeys) ctHandle.set(lastKnownKeys); + } + }; + } +}); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./filter":2,"./input":6}],8:[function(require,module,exports){ +(function (global){ +"use strict"; + +var _input = require("./input"); + +var input = _interopRequireWildcard(_input); + +var _util = require("./util"); + +var util = _interopRequireWildcard(_util); + +var _filter = require("./filter"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var $ = global.jQuery; + +input.register({ + className: "crosstalk-input-select", + + factory: function factory(el, data) { + /* + * items: {value: [...], label: [...]} + * map: {"groupA": ["keyA", "keyB", ...], ...} + * group: "ct-groupname" + */ + + var first = [{ value: "", label: "(All)" }]; + var items = util.dataframeToD3(data.items); + var opts = { + options: first.concat(items), + valueField: "value", + labelField: "label", + searchField: "label" + }; + + var select = $(el).find("select")[0]; + + var selectize = $(select).selectize(opts)[0].selectize; + + var ctHandle = new _filter.FilterHandle(data.group); + + var lastKnownKeys = void 0; + selectize.on("change", function () { + if (selectize.items.length === 0) { + lastKnownKeys = null; + ctHandle.clear(); + } else { + var keys = {}; + selectize.items.forEach(function (group) { + data.map[group].forEach(function (key) { + keys[key] = true; + }); + }); + var keyArray = Object.keys(keys); + keyArray.sort(); + lastKnownKeys = keyArray; + ctHandle.set(keyArray); + } + }); + + return { + suspend: function suspend() { + ctHandle.clear(); + }, + resume: function resume() { + if (lastKnownKeys) ctHandle.set(lastKnownKeys); + } + }; + } +}); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./filter":2,"./input":6,"./util":11}],9:[function(require,module,exports){ +(function (global){ +"use strict"; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _input = require("./input"); + +var input = _interopRequireWildcard(_input); + +var _filter = require("./filter"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var $ = global.jQuery; +var strftime = global.strftime; + +input.register({ + className: "crosstalk-input-slider", + + factory: function factory(el, data) { + /* + * map: {"groupA": ["keyA", "keyB", ...], ...} + * group: "ct-groupname" + */ + var ctHandle = new _filter.FilterHandle(data.group); + + var opts = {}; + var $el = $(el).find("input"); + var dataType = $el.data("data-type"); + var timeFormat = $el.data("time-format"); + var round = $el.data("round"); + var timeFormatter = void 0; + + // Set up formatting functions + if (dataType === "date") { + timeFormatter = strftime.utc(); + opts.prettify = function (num) { + return timeFormatter(timeFormat, new Date(num)); + }; + } else if (dataType === "datetime") { + var timezone = $el.data("timezone"); + if (timezone) timeFormatter = strftime.timezone(timezone);else timeFormatter = strftime; + + opts.prettify = function (num) { + return timeFormatter(timeFormat, new Date(num)); + }; + } else if (dataType === "number") { + if (typeof round !== "undefined") opts.prettify = function (num) { + var factor = Math.pow(10, round); + return Math.round(num * factor) / factor; + }; + } + + $el.ionRangeSlider(opts); + + function getValue() { + var result = $el.data("ionRangeSlider").result; + + // Function for converting numeric value from slider to appropriate type. + var convert = void 0; + var dataType = $el.data("data-type"); + if (dataType === "date") { + convert = function convert(val) { + return formatDateUTC(new Date(+val)); + }; + } else if (dataType === "datetime") { + convert = function convert(val) { + // Convert ms to s + return +val / 1000; + }; + } else { + convert = function convert(val) { + return +val; + }; + } + + if ($el.data("ionRangeSlider").options.type === "double") { + return [convert(result.from), convert(result.to)]; + } else { + return convert(result.from); + } + } + + var lastKnownKeys = null; + + $el.on("change.crosstalkSliderInput", function (event) { + if (!$el.data("updating") && !$el.data("animating")) { + var _getValue = getValue(), + _getValue2 = _slicedToArray(_getValue, 2), + from = _getValue2[0], + to = _getValue2[1]; + + var keys = []; + for (var i = 0; i < data.values.length; i++) { + var val = data.values[i]; + if (val >= from && val <= to) { + keys.push(data.keys[i]); + } + } + keys.sort(); + ctHandle.set(keys); + lastKnownKeys = keys; + } + }); + + // let $el = $(el); + // $el.on("change", "input[type="checkbox"]", function() { + // let checked = $el.find("input[type="checkbox"]:checked"); + // if (checked.length === 0) { + // ctHandle.clear(); + // } else { + // let keys = {}; + // checked.each(function() { + // data.map[this.value].forEach(function(key) { + // keys[key] = true; + // }); + // }); + // let keyArray = Object.keys(keys); + // keyArray.sort(); + // ctHandle.set(keyArray); + // } + // }); + + return { + suspend: function suspend() { + ctHandle.clear(); + }, + resume: function resume() { + if (lastKnownKeys) ctHandle.set(lastKnownKeys); + } + }; + } +}); + +// Convert a number to a string with leading zeros +function padZeros(n, digits) { + var str = n.toString(); + while (str.length < digits) { + str = "0" + str; + }return str; +} + +// Given a Date object, return a string in yyyy-mm-dd format, using the +// UTC date. This may be a day off from the date in the local time zone. +function formatDateUTC(date) { + if (date instanceof Date) { + return date.getUTCFullYear() + "-" + padZeros(date.getUTCMonth() + 1, 2) + "-" + padZeros(date.getUTCDate(), 2); + } else { + return null; + } +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./filter":2,"./input":6}],10:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SelectionHandle = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _events = require("./events"); + +var _events2 = _interopRequireDefault(_events); + +var _group = require("./group"); + +var _group2 = _interopRequireDefault(_group); + +var _util = require("./util"); + +var util = _interopRequireWildcard(_util); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** + * Use this class to read and write (and listen for changes to) the selection + * for a Crosstalk group. This is intended to be used for linked brushing. + * + * If two (or more) `SelectionHandle` instances in the same webpage share the + * same group name, they will share the same state. Setting the selection using + * one `SelectionHandle` instance will result in the `value` property instantly + * changing across the others, and `"change"` event listeners on all instances + * (including the one that initiated the sending) will fire. + * + * @param {string} [group] - The name of the Crosstalk group, or if none, + * null or undefined (or any other falsy value). This can be changed later + * via the [SelectionHandle#setGroup](#setGroup) method. + * @param {Object} [extraInfo] - An object whose properties will be copied to + * the event object whenever an event is emitted. + */ +var SelectionHandle = exports.SelectionHandle = function () { + function SelectionHandle() { + var group = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var extraInfo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + _classCallCheck(this, SelectionHandle); + + this._eventRelay = new _events2.default(); + this._emitter = new util.SubscriptionTracker(this._eventRelay); + + // Name of the group we're currently tracking, if any. Can change over time. + this._group = null; + // The Var we're currently tracking, if any. Can change over time. + this._var = null; + // The event handler subscription we currently have on var.on("change"). + this._varOnChangeSub = null; + + this._extraInfo = util.extend({ sender: this }, extraInfo); + + this.setGroup(group); + } + + /** + * Changes the Crosstalk group membership of this SelectionHandle. The group + * being switched away from (if any) will not have its selection value + * modified as a result of calling `setGroup`, even if this handle was the + * most recent handle to set the selection of the group. + * + * The group being switched to (if any) will also not have its selection value + * modified as a result of calling `setGroup`. If you want to set the + * selection value of the new group, call `set` explicitly. + * + * @param {string} group - The name of the Crosstalk group, or null (or + * undefined) to clear the group. + */ + + + _createClass(SelectionHandle, [{ + key: "setGroup", + value: function setGroup(group) { + var _this = this; + + // If group is unchanged, do nothing + if (this._group === group) return; + // Treat null, undefined, and other falsy values the same + if (!this._group && !group) return; + + if (this._var) { + this._var.off("change", this._varOnChangeSub); + this._var = null; + this._varOnChangeSub = null; + } + + this._group = group; + + if (group) { + this._var = (0, _group2.default)(group).var("selection"); + var sub = this._var.on("change", function (e) { + _this._eventRelay.trigger("change", e, _this); + }); + this._varOnChangeSub = sub; + } + } + + /** + * Retrieves the current selection for the group represented by this + * `SelectionHandle`. + * + * - If no selection is active, then this value will be falsy. + * - If a selection is active, but no data points are selected, then this + * value will be an empty array. + * - If a selection is active, and data points are selected, then the keys + * of the selected data points will be present in the array. + */ + + }, { + key: "_mergeExtraInfo", + + + /** + * Combines the given `extraInfo` (if any) with the handle's default + * `_extraInfo` (if any). + * @private + */ + value: function _mergeExtraInfo(extraInfo) { + // Important incidental effect: shallow clone is returned + return util.extend({}, this._extraInfo ? this._extraInfo : null, extraInfo ? extraInfo : null); + } + + /** + * Overwrites the current selection for the group, and raises the `"change"` + * event among all of the group's '`SelectionHandle` instances (including + * this one). + * + * @fires SelectionHandle#change + * @param {string[]} selectedKeys - Falsy, empty array, or array of keys (see + * {@link SelectionHandle#value}). + * @param {Object} [extraInfo] - Extra properties to be included on the event + * object that's passed to listeners (in addition to any options that were + * passed into the `SelectionHandle` constructor). + */ + + }, { + key: "set", + value: function set(selectedKeys, extraInfo) { + if (this._var) this._var.set(selectedKeys, this._mergeExtraInfo(extraInfo)); + } + + /** + * Overwrites the current selection for the group, and raises the `"change"` + * event among all of the group's '`SelectionHandle` instances (including + * this one). + * + * @fires SelectionHandle#change + * @param {Object} [extraInfo] - Extra properties to be included on the event + * object that's passed to listeners (in addition to any that were passed + * into the `SelectionHandle` constructor). + */ + + }, { + key: "clear", + value: function clear(extraInfo) { + if (this._var) this.set(void 0, this._mergeExtraInfo(extraInfo)); + } + + /** + * Subscribes to events on this `SelectionHandle`. + * + * @param {string} eventType - Indicates the type of events to listen to. + * Currently, only `"change"` is supported. + * @param {SelectionHandle~listener} listener - The callback function that + * will be invoked when the event occurs. + * @return {string} - A token to pass to {@link SelectionHandle#off} to cancel + * this subscription. + */ + + }, { + key: "on", + value: function on(eventType, listener) { + return this._emitter.on(eventType, listener); + } + + /** + * Cancels event subscriptions created by {@link SelectionHandle#on}. + * + * @param {string} eventType - The type of event to unsubscribe. + * @param {string|SelectionHandle~listener} listener - Either the callback + * function previously passed into {@link SelectionHandle#on}, or the + * string that was returned from {@link SelectionHandle#on}. + */ + + }, { + key: "off", + value: function off(eventType, listener) { + return this._emitter.off(eventType, listener); + } + + /** + * Shuts down the `SelectionHandle` object. + * + * Removes all event listeners that were added through this handle. + */ + + }, { + key: "close", + value: function close() { + this._emitter.removeAllListeners(); + this.setGroup(null); + } + }, { + key: "value", + get: function get() { + return this._var ? this._var.get() : null; + } + }]); + + return SelectionHandle; +}(); + +/** + * @callback SelectionHandle~listener + * @param {Object} event - An object containing details of the event. For + * `"change"` events, this includes the properties `value` (the new + * value of the selection, or `undefined` if no selection is active), + * `oldValue` (the previous value of the selection), and `sender` (the + * `SelectionHandle` instance that made the change). + */ + +/** + * @event SelectionHandle#change + * @type {object} + * @property {object} value - The new value of the selection, or `undefined` + * if no selection is active. + * @property {object} oldValue - The previous value of the selection. + * @property {SelectionHandle} sender - The `SelectionHandle` instance that + * changed the value. + */ + +},{"./events":1,"./group":4,"./util":11}],11:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +exports.extend = extend; +exports.checkSorted = checkSorted; +exports.diffSortedLists = diffSortedLists; +exports.dataframeToD3 = dataframeToD3; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function extend(target) { + for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; + } + + for (var i = 0; i < sources.length; i++) { + var src = sources[i]; + if (typeof src === "undefined" || src === null) continue; + + for (var key in src) { + if (src.hasOwnProperty(key)) { + target[key] = src[key]; + } + } + } + return target; +} + +function checkSorted(list) { + for (var i = 1; i < list.length; i++) { + if (list[i] <= list[i - 1]) { + throw new Error("List is not sorted or contains duplicate"); + } + } +} + +function diffSortedLists(a, b) { + var i_a = 0; + var i_b = 0; + + if (!a) a = []; + if (!b) b = []; + + var a_only = []; + var b_only = []; + + checkSorted(a); + checkSorted(b); + + while (i_a < a.length && i_b < b.length) { + if (a[i_a] === b[i_b]) { + i_a++; + i_b++; + } else if (a[i_a] < b[i_b]) { + a_only.push(a[i_a++]); + } else { + b_only.push(b[i_b++]); + } + } + + if (i_a < a.length) a_only = a_only.concat(a.slice(i_a)); + if (i_b < b.length) b_only = b_only.concat(b.slice(i_b)); + return { + removed: a_only, + added: b_only + }; +} + +// Convert from wide: { colA: [1,2,3], colB: [4,5,6], ... } +// to long: [ {colA: 1, colB: 4}, {colA: 2, colB: 5}, ... ] +function dataframeToD3(df) { + var names = []; + var length = void 0; + for (var name in df) { + if (df.hasOwnProperty(name)) names.push(name); + if (_typeof(df[name]) !== "object" || typeof df[name].length === "undefined") { + throw new Error("All fields must be arrays"); + } else if (typeof length !== "undefined" && length !== df[name].length) { + throw new Error("All fields must be arrays of the same length"); + } + length = df[name].length; + } + var results = []; + var item = void 0; + for (var row = 0; row < length; row++) { + item = {}; + for (var col = 0; col < names.length; col++) { + item[names[col]] = df[names[col]][row]; + } + results.push(item); + } + return results; +} + +/** + * Keeps track of all event listener additions/removals and lets all active + * listeners be removed with a single operation. + * + * @private + */ + +var SubscriptionTracker = exports.SubscriptionTracker = function () { + function SubscriptionTracker(emitter) { + _classCallCheck(this, SubscriptionTracker); + + this._emitter = emitter; + this._subs = {}; + } + + _createClass(SubscriptionTracker, [{ + key: "on", + value: function on(eventType, listener) { + var sub = this._emitter.on(eventType, listener); + this._subs[sub] = eventType; + return sub; + } + }, { + key: "off", + value: function off(eventType, listener) { + var sub = this._emitter.off(eventType, listener); + if (sub) { + delete this._subs[sub]; + } + return sub; + } + }, { + key: "removeAllListeners", + value: function removeAllListeners() { + var _this = this; + + var current_subs = this._subs; + this._subs = {}; + Object.keys(current_subs).forEach(function (sub) { + _this._emitter.off(current_subs[sub], sub); + }); + } + }]); + + return SubscriptionTracker; +}(); + +},{}],12:[function(require,module,exports){ +(function (global){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _events = require("./events"); + +var _events2 = _interopRequireDefault(_events); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Var = function () { + function Var(group, name, /*optional*/value) { + _classCallCheck(this, Var); + + this._group = group; + this._name = name; + this._value = value; + this._events = new _events2.default(); + } + + _createClass(Var, [{ + key: "get", + value: function get() { + return this._value; + } + }, { + key: "set", + value: function set(value, /*optional*/event) { + if (this._value === value) { + // Do nothing; the value hasn't changed + return; + } + var oldValue = this._value; + this._value = value; + // Alert JavaScript listeners that the value has changed + var evt = {}; + if (event && (typeof event === "undefined" ? "undefined" : _typeof(event)) === "object") { + for (var k in event) { + if (event.hasOwnProperty(k)) evt[k] = event[k]; + } + } + evt.oldValue = oldValue; + evt.value = value; + this._events.trigger("change", evt, this); + + // TODO: Make this extensible, to let arbitrary back-ends know that + // something has changed + if (global.Shiny && global.Shiny.onInputChange) { + global.Shiny.onInputChange(".clientValue-" + (this._group.name !== null ? this._group.name + "-" : "") + this._name, typeof value === "undefined" ? null : value); + } + } + }, { + key: "on", + value: function on(eventType, listener) { + return this._events.on(eventType, listener); + } + }, { + key: "off", + value: function off(eventType, listener) { + return this._events.off(eventType, listener); + } + }]); + + return Var; +}(); + +exports.default = Var; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./events":1}]},{},[5]) +//# sourceMappingURL=crosstalk.js.map diff --git a/docs/site_libs/crosstalk-1.2.1/js/crosstalk.js.map b/docs/site_libs/crosstalk-1.2.1/js/crosstalk.js.map new file mode 100644 index 000000000..cff94f089 --- /dev/null +++ b/docs/site_libs/crosstalk-1.2.1/js/crosstalk.js.map @@ -0,0 +1,37 @@ +{ + "version": 3, + "sources": [ + "node_modules/browser-pack/_prelude.js", + "javascript/src/events.js", + "javascript/src/filter.js", + "javascript/src/filterset.js", + "javascript/src/group.js", + "javascript/src/index.js", + "javascript/src/input.js", + "javascript/src/input_checkboxgroup.js", + "javascript/src/input_selectize.js", + "javascript/src/input_slider.js", + "javascript/src/selection.js", + "javascript/src/util.js", + "javascript/src/var.js" + ], + "names": [], + "mappings": "AAAA;;;;;;;;;;;ICAqB,M;AACnB,oBAAc;AAAA;;AACZ,SAAK,MAAL,GAAc,EAAd;AACA,SAAK,IAAL,GAAY,CAAZ;AACD;;;;uBAEE,S,EAAW,Q,EAAU;AACtB,UAAI,OAAO,KAAK,MAAL,CAAY,SAAZ,CAAX;AACA,UAAI,CAAC,IAAL,EAAW;AACT,eAAO,KAAK,MAAL,CAAY,SAAZ,IAAyB,EAAhC;AACD;AACD,UAAI,MAAM,QAAS,KAAK,IAAL,EAAnB;AACA,WAAK,GAAL,IAAY,QAAZ;AACA,aAAO,GAAP;AACD;;AAED;;;;wBACI,S,EAAW,Q,EAAU;AACvB,UAAI,OAAO,KAAK,MAAL,CAAY,SAAZ,CAAX;AACA,UAAI,OAAO,QAAP,KAAqB,UAAzB,EAAqC;AACnC,aAAK,IAAI,GAAT,IAAgB,IAAhB,EAAsB;AACpB,cAAI,KAAK,cAAL,CAAoB,GAApB,CAAJ,EAA8B;AAC5B,gBAAI,KAAK,GAAL,MAAc,QAAlB,EAA4B;AAC1B,qBAAO,KAAK,GAAL,CAAP;AACA,qBAAO,GAAP;AACD;AACF;AACF;AACD,eAAO,KAAP;AACD,OAVD,MAUO,IAAI,OAAO,QAAP,KAAqB,QAAzB,EAAmC;AACxC,YAAI,QAAQ,KAAK,QAAL,CAAZ,EAA4B;AAC1B,iBAAO,KAAK,QAAL,CAAP;AACA,iBAAO,QAAP;AACD;AACD,eAAO,KAAP;AACD,OANM,MAMA;AACL,cAAM,IAAI,KAAJ,CAAU,8BAAV,CAAN;AACD;AACF;;;4BAEO,S,EAAW,G,EAAK,O,EAAS;AAC/B,UAAI,OAAO,KAAK,MAAL,CAAY,SAAZ,CAAX;AACA,WAAK,IAAI,GAAT,IAAgB,IAAhB,EAAsB;AACpB,YAAI,KAAK,cAAL,CAAoB,GAApB,CAAJ,EAA8B;AAC5B,eAAK,GAAL,EAAU,IAAV,CAAe,OAAf,EAAwB,GAAxB;AACD;AACF;AACF;;;;;;kBA/CkB,M;;;;;;;;;;;;ACArB;;;;AACA;;;;AACA;;;;AACA;;IAAY,I;;;;;;;;AAEZ,SAAS,YAAT,CAAsB,KAAtB,EAA6B;AAC3B,MAAI,QAAQ,MAAM,GAAN,CAAU,WAAV,CAAZ;AACA,MAAI,SAAS,MAAM,GAAN,EAAb;AACA,MAAI,CAAC,MAAL,EAAa;AACX,aAAS,yBAAT;AACA,UAAM,GAAN,CAAU,MAAV;AACD;AACD,SAAO,MAAP;AACD;;AAED,IAAI,KAAK,CAAT;AACA,SAAS,MAAT,GAAkB;AAChB,SAAO,IAAP;AACD;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;IAwBa,Y,WAAA,Y;AACX,wBAAY,KAAZ,EAAmB,SAAnB,EAA8B;AAAA;;AAC5B,SAAK,WAAL,GAAmB,sBAAnB;AACA,SAAK,QAAL,GAAgB,IAAI,KAAK,mBAAT,CAA6B,KAAK,WAAlC,CAAhB;;AAEA;AACA,SAAK,MAAL,GAAc,IAAd;AACA;AACA,SAAK,UAAL,GAAkB,IAAlB;AACA;AACA,SAAK,UAAL,GAAkB,IAAlB;AACA;AACA,SAAK,eAAL,GAAuB,IAAvB;;AAEA,SAAK,UAAL,GAAkB,KAAK,MAAL,CAAY,EAAE,QAAQ,IAAV,EAAZ,EAA8B,SAA9B,CAAlB;;AAEA,SAAK,GAAL,GAAW,WAAW,QAAtB;;AAEA,SAAK,QAAL,CAAc,KAAd;AACD;;AAED;;;;;;;;;;;;;;6BAUS,K,EAAO;AAAA;;AACd;AACA,UAAI,KAAK,MAAL,KAAgB,KAApB,EACE;AACF;AACA,UAAI,CAAC,KAAK,MAAN,IAAgB,CAAC,KAArB,EACE;;AAEF,UAAI,KAAK,UAAT,EAAqB;AACnB,aAAK,UAAL,CAAgB,GAAhB,CAAoB,QAApB,EAA8B,KAAK,eAAnC;AACA,aAAK,KAAL;AACA,aAAK,eAAL,GAAuB,IAAvB;AACA,aAAK,UAAL,GAAkB,IAAlB;AACA,aAAK,UAAL,GAAkB,IAAlB;AACD;;AAED,WAAK,MAAL,GAAc,KAAd;;AAEA,UAAI,KAAJ,EAAW;AACT,gBAAQ,qBAAI,KAAJ,CAAR;AACA,aAAK,UAAL,GAAkB,aAAa,KAAb,CAAlB;AACA,aAAK,UAAL,GAAkB,qBAAI,KAAJ,EAAW,GAAX,CAAe,QAAf,CAAlB;AACA,YAAI,MAAM,KAAK,UAAL,CAAgB,EAAhB,CAAmB,QAAnB,EAA6B,UAAC,CAAD,EAAO;AAC5C,gBAAK,WAAL,CAAiB,OAAjB,CAAyB,QAAzB,EAAmC,CAAnC;AACD,SAFS,CAAV;AAGA,aAAK,eAAL,GAAuB,GAAvB;AACD;AACF;;AAED;;;;;;;;oCAKgB,S,EAAW;AACzB,aAAO,KAAK,MAAL,CAAY,EAAZ,EACL,KAAK,UAAL,GAAkB,KAAK,UAAvB,GAAoC,IAD/B,EAEL,YAAY,SAAZ,GAAwB,IAFnB,CAAP;AAGD;;AAED;;;;;;;4BAIQ;AACN,WAAK,QAAL,CAAc,kBAAd;AACA,WAAK,KAAL;AACA,WAAK,QAAL,CAAc,IAAd;AACD;;AAED;;;;;;;;;;;;0BASM,S,EAAW;AACf,UAAI,CAAC,KAAK,UAAV,EACE;AACF,WAAK,UAAL,CAAgB,KAAhB,CAAsB,KAAK,GAA3B;AACA,WAAK,SAAL,CAAe,SAAf;AACD;;AAED;;;;;;;;;;;;;;;;;;;;wBAiBI,I,EAAM,S,EAAW;AACnB,UAAI,CAAC,KAAK,UAAV,EACE;AACF,WAAK,UAAL,CAAgB,MAAhB,CAAuB,KAAK,GAA5B,EAAiC,IAAjC;AACA,WAAK,SAAL,CAAe,SAAf;AACD;;AAED;;;;;;;;;;AASA;;;;;;;;;;uBAUG,S,EAAW,Q,EAAU;AACtB,aAAO,KAAK,QAAL,CAAc,EAAd,CAAiB,SAAjB,EAA4B,QAA5B,CAAP;AACD;;AAED;;;;;;;;;;;wBAQI,S,EAAW,Q,EAAU;AACvB,aAAO,KAAK,QAAL,CAAc,GAAd,CAAkB,SAAlB,EAA6B,QAA7B,CAAP;AACD;;;8BAES,S,EAAW;AACnB,UAAI,CAAC,KAAK,UAAV,EACE;AACF,WAAK,UAAL,CAAgB,GAAhB,CAAoB,KAAK,UAAL,CAAgB,KAApC,EAA2C,KAAK,eAAL,CAAqB,SAArB,CAA3C;AACD;;AAED;;;;;;;;;;;wBApCmB;AACjB,aAAO,KAAK,UAAL,GAAkB,KAAK,UAAL,CAAgB,KAAlC,GAA0C,IAAjD;AACD;;;;;;AA6CH;;;;;;;;;;;;;;;;;;;ACzNA;;;;AAEA,SAAS,iBAAT,CAA2B,CAA3B,EAA8B,CAA9B,EAAiC;AAC/B,MAAI,MAAM,CAAV,EAAa;AACX,WAAO,CAAP;AACD,GAFD,MAEO,IAAI,IAAI,CAAR,EAAW;AAChB,WAAO,CAAC,CAAR;AACD,GAFM,MAEA,IAAI,IAAI,CAAR,EAAW;AAChB,WAAO,CAAP;AACD;AACF;;AAED;;;;IAGqB,S;AACnB,uBAAc;AAAA;;AACZ,SAAK,KAAL;AACD;;;;4BAEO;AACN;AACA,WAAK,QAAL,GAAgB,EAAhB;AACA;AACA,WAAK,KAAL,GAAa,EAAb;AACA,WAAK,MAAL,GAAc,IAAd;AACA,WAAK,cAAL,GAAsB,CAAtB;AACD;;;2BAMM,Q,EAAU,I,EAAM;AACrB,UAAI,SAAS,IAAb,EAAmB;AACjB,eAAO,KAAK,KAAL,CAAW,CAAX,CAAP,CADiB,CACK;AACtB,aAAK,IAAL,CAAU,iBAAV;AACD;;AAJoB,6BAME,2BAAgB,KAAK,QAAL,CAAc,QAAd,CAAhB,EAAyC,IAAzC,CANF;AAAA,UAMhB,KANgB,oBAMhB,KANgB;AAAA,UAMT,OANS,oBAMT,OANS;;AAOrB,WAAK,QAAL,CAAc,QAAd,IAA0B,IAA1B;;AAEA,WAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,MAAM,MAA1B,EAAkC,GAAlC,EAAuC;AACrC,aAAK,KAAL,CAAW,MAAM,CAAN,CAAX,IAAuB,CAAC,KAAK,KAAL,CAAW,MAAM,CAAN,CAAX,KAAwB,CAAzB,IAA8B,CAArD;AACD;AACD,WAAK,IAAI,KAAI,CAAb,EAAgB,KAAI,QAAQ,MAA5B,EAAoC,IAApC,EAAyC;AACvC,aAAK,KAAL,CAAW,QAAQ,EAAR,CAAX;AACD;;AAED,WAAK,YAAL,CAAkB,IAAlB;AACD;;AAED;;;;;;;;mCAKmC;AAAA,UAAtB,IAAsB,uEAAf,KAAK,QAAU;;AACjC,UAAI,cAAc,OAAO,IAAP,CAAY,KAAK,QAAjB,EAA2B,MAA7C;AACA,UAAI,gBAAgB,CAApB,EAAuB;AACrB,aAAK,MAAL,GAAc,IAAd;AACD,OAFD,MAEO;AACL,aAAK,MAAL,GAAc,EAAd;AACA,aAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAzB,EAAiC,GAAjC,EAAsC;AACpC,cAAI,QAAQ,KAAK,KAAL,CAAW,KAAK,CAAL,CAAX,CAAZ;AACA,cAAI,UAAU,WAAd,EAA2B;AACzB,iBAAK,MAAL,CAAY,IAAZ,CAAiB,KAAK,CAAL,CAAjB;AACD;AACF;AACF;AACF;;;0BAEK,Q,EAAU;AACd,UAAI,OAAO,KAAK,QAAL,CAAc,QAAd,CAAP,KAAoC,WAAxC,EAAqD;AACnD;AACD;;AAED,UAAI,OAAO,KAAK,QAAL,CAAc,QAAd,CAAX;AACA,UAAI,CAAC,IAAL,EAAW;AACT,eAAO,EAAP;AACD;;AAED,WAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAzB,EAAiC,GAAjC,EAAsC;AACpC,aAAK,KAAL,CAAW,KAAK,CAAL,CAAX;AACD;AACD,aAAO,KAAK,QAAL,CAAc,QAAd,CAAP;;AAEA,WAAK,YAAL;AACD;;;wBA3DW;AACV,aAAO,KAAK,MAAZ;AACD;;;wBA2Dc;AACb,UAAI,UAAU,OAAO,IAAP,CAAY,KAAK,KAAjB,CAAd;AACA,cAAQ,IAAR,CAAa,iBAAb;AACA,aAAO,OAAP;AACD;;;;;;kBA/EkB,S;;;;;;;;;;;;;;kBCRG,K;;AAPxB;;;;;;;;AAEA;AACA;AACA,OAAO,kBAAP,GAA4B,OAAO,kBAAP,IAA6B,EAAzD;AACA,IAAI,SAAS,OAAO,kBAApB;;AAEe,SAAS,KAAT,CAAe,SAAf,EAA0B;AACvC,MAAI,aAAa,OAAO,SAAP,KAAsB,QAAvC,EAAiD;AAC/C,QAAI,CAAC,OAAO,cAAP,CAAsB,SAAtB,CAAL,EAAuC;AACrC,aAAO,SAAP,IAAoB,IAAI,KAAJ,CAAU,SAAV,CAApB;AACD;AACD,WAAO,OAAO,SAAP,CAAP;AACD,GALD,MAKO,IAAI,QAAO,SAAP,yCAAO,SAAP,OAAsB,QAAtB,IAAkC,UAAU,KAA5C,IAAqD,UAAU,GAAnE,EAAwE;AAC7E;AACA,WAAO,SAAP;AACD,GAHM,MAGA,IAAI,MAAM,OAAN,CAAc,SAAd,KACP,UAAU,MAAV,IAAoB,CADb,IAEP,OAAO,UAAU,CAAV,CAAP,KAAyB,QAFtB,EAEgC;AACrC,WAAO,MAAM,UAAU,CAAV,CAAN,CAAP;AACD,GAJM,MAIA;AACL,UAAM,IAAI,KAAJ,CAAU,4BAAV,CAAN;AACD;AACF;;IAEK,K;AACJ,iBAAY,IAAZ,EAAkB;AAAA;;AAChB,SAAK,IAAL,GAAY,IAAZ;AACA,SAAK,KAAL,GAAa,EAAb;AACD;;;;yBAEG,I,EAAM;AACR,UAAI,CAAC,IAAD,IAAS,OAAO,IAAP,KAAiB,QAA9B,EAAwC;AACtC,cAAM,IAAI,KAAJ,CAAU,kBAAV,CAAN;AACD;;AAED,UAAI,CAAC,KAAK,KAAL,CAAW,cAAX,CAA0B,IAA1B,CAAL,EACE,KAAK,KAAL,CAAW,IAAX,IAAmB,kBAAQ,IAAR,EAAc,IAAd,CAAnB;AACF,aAAO,KAAK,KAAL,CAAW,IAAX,CAAP;AACD;;;wBAEG,I,EAAM;AACR,UAAI,CAAC,IAAD,IAAS,OAAO,IAAP,KAAiB,QAA9B,EAAwC;AACtC,cAAM,IAAI,KAAJ,CAAU,kBAAV,CAAN;AACD;;AAED,aAAO,KAAK,KAAL,CAAW,cAAX,CAA0B,IAA1B,CAAP;AACD;;;;;;;;;;;;;;;;AC/CH;;;;AACA;;AACA;;AACA;;AACA;;AACA;;AACA;;;;AAEA,IAAM,eAAe,qBAAM,SAAN,CAArB;;AAEA,SAAS,IAAT,CAAc,IAAd,EAAoB;AAClB,SAAO,aAAa,GAAb,CAAiB,IAAjB,CAAP;AACD;;AAED,SAAS,GAAT,CAAa,IAAb,EAAmB;AACjB,SAAO,aAAa,GAAb,CAAiB,IAAjB,CAAP;AACD;;AAED,IAAI,OAAO,KAAX,EAAkB;AAChB,SAAO,KAAP,CAAa,uBAAb,CAAqC,qBAArC,EAA4D,UAAS,OAAT,EAAkB;AAC5E,QAAI,OAAO,QAAQ,KAAf,KAA0B,QAA9B,EAAwC;AACtC,2BAAM,QAAQ,KAAd,EAAqB,GAArB,CAAyB,QAAQ,IAAjC,EAAuC,GAAvC,CAA2C,QAAQ,KAAnD;AACD,KAFD,MAEO;AACL,WAAK,QAAQ,IAAb,EAAmB,GAAnB,CAAuB,QAAQ,KAA/B;AACD;AACF,GAND;AAOD;;AAED,IAAM,YAAY;AAChB,wBADgB;AAEhB,OAAK,IAFW;AAGhB,OAAK,GAHW;AAIhB,6CAJgB;AAKhB,oCALgB;AAMhB;AANgB,CAAlB;;AASA;;;kBAGe,S;;AACf,OAAO,SAAP,GAAmB,SAAnB;;;;;;;;;;;QCrCgB,Q,GAAA,Q;QAWA,I,GAAA,I;AAfhB,IAAI,IAAI,OAAO,MAAf;;AAEA,IAAI,WAAW,EAAf;;AAEO,SAAS,QAAT,CAAkB,GAAlB,EAAuB;AAC5B,WAAS,IAAI,SAAb,IAA0B,GAA1B;AACA,MAAI,OAAO,QAAP,IAAmB,OAAO,QAAP,CAAgB,UAAhB,KAA+B,UAAtD,EAAkE;AAChE,MAAE,YAAM;AACN;AACD,KAFD;AAGD,GAJD,MAIO,IAAI,OAAO,QAAX,EAAqB;AAC1B,eAAW,IAAX,EAAiB,GAAjB;AACD;AACF;;AAEM,SAAS,IAAT,GAAgB;AACrB,SAAO,IAAP,CAAY,QAAZ,EAAsB,OAAtB,CAA8B,UAAS,SAAT,EAAoB;AAChD,QAAI,UAAU,SAAS,SAAT,CAAd;AACA,MAAE,MAAM,QAAQ,SAAhB,EAA2B,GAA3B,CAA+B,wBAA/B,EAAyD,IAAzD,CAA8D,UAAS,CAAT,EAAY,EAAZ,EAAgB;AAC5E,mBAAa,OAAb,EAAsB,EAAtB;AACD,KAFD;AAGD,GALD;AAMD;;AAED;AACA,SAAS,OAAT,CAAiB,GAAjB,EAAsB;AACpB,SAAO,IAAI,OAAJ,CAAY,uCAAZ,EAAqD,MAArD,CAAP;AACD;;AAED,SAAS,MAAT,CAAgB,EAAhB,EAAoB;AAClB,MAAI,MAAM,EAAE,EAAF,CAAV;AACA,SAAO,IAAP,CAAY,QAAZ,EAAsB,OAAtB,CAA8B,UAAS,SAAT,EAAoB;AAChD,QAAI,IAAI,QAAJ,CAAa,SAAb,KAA2B,CAAC,IAAI,QAAJ,CAAa,uBAAb,CAAhC,EAAuE;AACrE,UAAI,UAAU,SAAS,SAAT,CAAd;AACA,mBAAa,OAAb,EAAsB,EAAtB;AACD;AACF,GALD;AAMD;;AAED,SAAS,YAAT,CAAsB,OAAtB,EAA+B,EAA/B,EAAmC;AACjC,MAAI,SAAS,EAAE,EAAF,EAAM,IAAN,CAAW,+CAA+C,QAAQ,GAAG,EAAX,CAA/C,GAAgE,IAA3E,CAAb;AACA,MAAI,OAAO,KAAK,KAAL,CAAW,OAAO,CAAP,EAAU,SAArB,CAAX;;AAEA,MAAI,WAAW,QAAQ,OAAR,CAAgB,EAAhB,EAAoB,IAApB,CAAf;AACA,IAAE,EAAF,EAAM,IAAN,CAAW,oBAAX,EAAiC,QAAjC;AACA,IAAE,EAAF,EAAM,QAAN,CAAe,uBAAf;AACD;;AAED,IAAI,OAAO,KAAX,EAAkB;AAChB,MAAI,eAAe,IAAI,OAAO,KAAP,CAAa,YAAjB,EAAnB;AACA,MAAI,KAAI,OAAO,MAAf;AACA,KAAE,MAAF,CAAS,YAAT,EAAuB;AACrB,UAAM,cAAS,KAAT,EAAgB;AACpB,aAAO,GAAE,KAAF,EAAS,IAAT,CAAc,kBAAd,CAAP;AACD,KAHoB;AAIrB,gBAAY,oBAAS,EAAT,EAAa;AACvB,UAAI,CAAC,GAAE,EAAF,EAAM,QAAN,CAAe,uBAAf,CAAL,EAA8C;AAC5C,eAAO,EAAP;AACD;AACF,KARoB;AASrB,WAAO,eAAS,EAAT,EAAa;AAClB,aAAO,GAAG,EAAV;AACD,KAXoB;AAYrB,cAAU,kBAAS,EAAT,EAAa,CAEtB,CAdoB;AAerB,cAAU,kBAAS,EAAT,EAAa,KAAb,EAAoB,CAE7B,CAjBoB;AAkBrB,oBAAgB,wBAAS,EAAT,EAAa,IAAb,EAAmB,CAElC,CApBoB;AAqBrB,eAAW,mBAAS,EAAT,EAAa,QAAb,EAAuB;AAChC,SAAE,EAAF,EAAM,IAAN,CAAW,oBAAX,EAAiC,MAAjC;AACD,KAvBoB;AAwBrB,iBAAa,qBAAS,EAAT,EAAa;AACxB,SAAE,EAAF,EAAM,IAAN,CAAW,oBAAX,EAAiC,OAAjC;AACD;AA1BoB,GAAvB;AA4BA,SAAO,KAAP,CAAa,aAAb,CAA2B,QAA3B,CAAoC,YAApC,EAAkD,wBAAlD;AACD;;;;;;;;AChFD;;IAAY,K;;AACZ;;;;AAEA,IAAI,IAAI,OAAO,MAAf;;AAEA,MAAM,QAAN,CAAe;AACb,aAAW,+BADE;;AAGb,WAAS,iBAAS,EAAT,EAAa,IAAb,EAAmB;AAC1B;;;;AAIA,QAAI,WAAW,yBAAiB,KAAK,KAAtB,CAAf;;AAEA,QAAI,sBAAJ;AACA,QAAI,MAAM,EAAE,EAAF,CAAV;AACA,QAAI,EAAJ,CAAO,QAAP,EAAiB,wBAAjB,EAA2C,YAAW;AACpD,UAAI,UAAU,IAAI,IAAJ,CAAS,gCAAT,CAAd;AACA,UAAI,QAAQ,MAAR,KAAmB,CAAvB,EAA0B;AACxB,wBAAgB,IAAhB;AACA,iBAAS,KAAT;AACD,OAHD,MAGO;AACL,YAAI,OAAO,EAAX;AACA,gBAAQ,IAAR,CAAa,YAAW;AACtB,eAAK,GAAL,CAAS,KAAK,KAAd,EAAqB,OAArB,CAA6B,UAAS,GAAT,EAAc;AACzC,iBAAK,GAAL,IAAY,IAAZ;AACD,WAFD;AAGD,SAJD;AAKA,YAAI,WAAW,OAAO,IAAP,CAAY,IAAZ,CAAf;AACA,iBAAS,IAAT;AACA,wBAAgB,QAAhB;AACA,iBAAS,GAAT,CAAa,QAAb;AACD;AACF,KAjBD;;AAmBA,WAAO;AACL,eAAS,mBAAW;AAClB,iBAAS,KAAT;AACD,OAHI;AAIL,cAAQ,kBAAW;AACjB,YAAI,aAAJ,EACE,SAAS,GAAT,CAAa,aAAb;AACH;AAPI,KAAP;AASD;AAxCY,CAAf;;;;;;;;ACLA;;IAAY,K;;AACZ;;IAAY,I;;AACZ;;;;AAEA,IAAI,IAAI,OAAO,MAAf;;AAEA,MAAM,QAAN,CAAe;AACb,aAAW,wBADE;;AAGb,WAAS,iBAAS,EAAT,EAAa,IAAb,EAAmB;AAC1B;;;;;;AAMA,QAAI,QAAQ,CAAC,EAAC,OAAO,EAAR,EAAY,OAAO,OAAnB,EAAD,CAAZ;AACA,QAAI,QAAQ,KAAK,aAAL,CAAmB,KAAK,KAAxB,CAAZ;AACA,QAAI,OAAO;AACT,eAAS,MAAM,MAAN,CAAa,KAAb,CADA;AAET,kBAAY,OAFH;AAGT,kBAAY,OAHH;AAIT,mBAAa;AAJJ,KAAX;;AAOA,QAAI,SAAS,EAAE,EAAF,EAAM,IAAN,CAAW,QAAX,EAAqB,CAArB,CAAb;;AAEA,QAAI,YAAY,EAAE,MAAF,EAAU,SAAV,CAAoB,IAApB,EAA0B,CAA1B,EAA6B,SAA7C;;AAEA,QAAI,WAAW,yBAAiB,KAAK,KAAtB,CAAf;;AAEA,QAAI,sBAAJ;AACA,cAAU,EAAV,CAAa,QAAb,EAAuB,YAAW;AAChC,UAAI,UAAU,KAAV,CAAgB,MAAhB,KAA2B,CAA/B,EAAkC;AAChC,wBAAgB,IAAhB;AACA,iBAAS,KAAT;AACD,OAHD,MAGO;AACL,YAAI,OAAO,EAAX;AACA,kBAAU,KAAV,CAAgB,OAAhB,CAAwB,UAAS,KAAT,EAAgB;AACtC,eAAK,GAAL,CAAS,KAAT,EAAgB,OAAhB,CAAwB,UAAS,GAAT,EAAc;AACpC,iBAAK,GAAL,IAAY,IAAZ;AACD,WAFD;AAGD,SAJD;AAKA,YAAI,WAAW,OAAO,IAAP,CAAY,IAAZ,CAAf;AACA,iBAAS,IAAT;AACA,wBAAgB,QAAhB;AACA,iBAAS,GAAT,CAAa,QAAb;AACD;AACF,KAhBD;;AAkBA,WAAO;AACL,eAAS,mBAAW;AAClB,iBAAS,KAAT;AACD,OAHI;AAIL,cAAQ,kBAAW;AACjB,YAAI,aAAJ,EACE,SAAS,GAAT,CAAa,aAAb;AACH;AAPI,KAAP;AASD;AArDY,CAAf;;;;;;;;;;ACNA;;IAAY,K;;AACZ;;;;AAEA,IAAI,IAAI,OAAO,MAAf;AACA,IAAI,WAAW,OAAO,QAAtB;;AAEA,MAAM,QAAN,CAAe;AACb,aAAW,wBADE;;AAGb,WAAS,iBAAS,EAAT,EAAa,IAAb,EAAmB;AAC1B;;;;AAIA,QAAI,WAAW,yBAAiB,KAAK,KAAtB,CAAf;;AAEA,QAAI,OAAO,EAAX;AACA,QAAI,MAAM,EAAE,EAAF,EAAM,IAAN,CAAW,OAAX,CAAV;AACA,QAAI,WAAW,IAAI,IAAJ,CAAS,WAAT,CAAf;AACA,QAAI,aAAa,IAAI,IAAJ,CAAS,aAAT,CAAjB;AACA,QAAI,QAAQ,IAAI,IAAJ,CAAS,OAAT,CAAZ;AACA,QAAI,sBAAJ;;AAEA;AACA,QAAI,aAAa,MAAjB,EAAyB;AACvB,sBAAgB,SAAS,GAAT,EAAhB;AACA,WAAK,QAAL,GAAgB,UAAS,GAAT,EAAc;AAC5B,eAAO,cAAc,UAAd,EAA0B,IAAI,IAAJ,CAAS,GAAT,CAA1B,CAAP;AACD,OAFD;AAID,KAND,MAMO,IAAI,aAAa,UAAjB,EAA6B;AAClC,UAAI,WAAW,IAAI,IAAJ,CAAS,UAAT,CAAf;AACA,UAAI,QAAJ,EACE,gBAAgB,SAAS,QAAT,CAAkB,QAAlB,CAAhB,CADF,KAGE,gBAAgB,QAAhB;;AAEF,WAAK,QAAL,GAAgB,UAAS,GAAT,EAAc;AAC5B,eAAO,cAAc,UAAd,EAA0B,IAAI,IAAJ,CAAS,GAAT,CAA1B,CAAP;AACD,OAFD;AAGD,KAVM,MAUA,IAAI,aAAa,QAAjB,EAA2B;AAChC,UAAI,OAAO,KAAP,KAAiB,WAArB,EACE,KAAK,QAAL,GAAgB,UAAS,GAAT,EAAc;AAC5B,YAAI,SAAS,KAAK,GAAL,CAAS,EAAT,EAAa,KAAb,CAAb;AACA,eAAO,KAAK,KAAL,CAAW,MAAM,MAAjB,IAA2B,MAAlC;AACD,OAHD;AAIH;;AAED,QAAI,cAAJ,CAAmB,IAAnB;;AAEA,aAAS,QAAT,GAAoB;AAClB,UAAI,SAAS,IAAI,IAAJ,CAAS,gBAAT,EAA2B,MAAxC;;AAEA;AACA,UAAI,gBAAJ;AACA,UAAI,WAAW,IAAI,IAAJ,CAAS,WAAT,CAAf;AACA,UAAI,aAAa,MAAjB,EAAyB;AACvB,kBAAU,iBAAS,GAAT,EAAc;AACtB,iBAAO,cAAc,IAAI,IAAJ,CAAS,CAAC,GAAV,CAAd,CAAP;AACD,SAFD;AAGD,OAJD,MAIO,IAAI,aAAa,UAAjB,EAA6B;AAClC,kBAAU,iBAAS,GAAT,EAAc;AACtB;AACA,iBAAO,CAAC,GAAD,GAAO,IAAd;AACD,SAHD;AAID,OALM,MAKA;AACL,kBAAU,iBAAS,GAAT,EAAc;AAAE,iBAAO,CAAC,GAAR;AAAc,SAAxC;AACD;;AAED,UAAI,IAAI,IAAJ,CAAS,gBAAT,EAA2B,OAA3B,CAAmC,IAAnC,KAA4C,QAAhD,EAA0D;AACxD,eAAO,CAAC,QAAQ,OAAO,IAAf,CAAD,EAAuB,QAAQ,OAAO,EAAf,CAAvB,CAAP;AACD,OAFD,MAEO;AACL,eAAO,QAAQ,OAAO,IAAf,CAAP;AACD;AACF;;AAED,QAAI,gBAAgB,IAApB;;AAEA,QAAI,EAAJ,CAAO,6BAAP,EAAsC,UAAS,KAAT,EAAgB;AACpD,UAAI,CAAC,IAAI,IAAJ,CAAS,UAAT,CAAD,IAAyB,CAAC,IAAI,IAAJ,CAAS,WAAT,CAA9B,EAAqD;AAAA,wBAClC,UADkC;AAAA;AAAA,YAC9C,IAD8C;AAAA,YACxC,EADwC;;AAEnD,YAAI,OAAO,EAAX;AACA,aAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAL,CAAY,MAAhC,EAAwC,GAAxC,EAA6C;AAC3C,cAAI,MAAM,KAAK,MAAL,CAAY,CAAZ,CAAV;AACA,cAAI,OAAO,IAAP,IAAe,OAAO,EAA1B,EAA8B;AAC5B,iBAAK,IAAL,CAAU,KAAK,IAAL,CAAU,CAAV,CAAV;AACD;AACF;AACD,aAAK,IAAL;AACA,iBAAS,GAAT,CAAa,IAAb;AACA,wBAAgB,IAAhB;AACD;AACF,KAdD;;AAiBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,WAAO;AACL,eAAS,mBAAW;AAClB,iBAAS,KAAT;AACD,OAHI;AAIL,cAAQ,kBAAW;AACjB,YAAI,aAAJ,EACE,SAAS,GAAT,CAAa,aAAb;AACH;AAPI,KAAP;AASD;AApHY,CAAf;;AAwHA;AACA,SAAS,QAAT,CAAkB,CAAlB,EAAqB,MAArB,EAA6B;AAC3B,MAAI,MAAM,EAAE,QAAF,EAAV;AACA,SAAO,IAAI,MAAJ,GAAa,MAApB;AACE,UAAM,MAAM,GAAZ;AADF,GAEA,OAAO,GAAP;AACD;;AAED;AACA;AACA,SAAS,aAAT,CAAuB,IAAvB,EAA6B;AAC3B,MAAI,gBAAgB,IAApB,EAA0B;AACxB,WAAO,KAAK,cAAL,KAAwB,GAAxB,GACA,SAAS,KAAK,WAAL,KAAmB,CAA5B,EAA+B,CAA/B,CADA,GACoC,GADpC,GAEA,SAAS,KAAK,UAAL,EAAT,EAA4B,CAA5B,CAFP;AAID,GALD,MAKO;AACL,WAAO,IAAP;AACD;AACF;;;;;;;;;;;;;;ACjJD;;;;AACA;;;;AACA;;IAAY,I;;;;;;;;AAEZ;;;;;;;;;;;;;;;;IAgBa,e,WAAA,e;AAEX,6BAA4C;AAAA,QAAhC,KAAgC,uEAAxB,IAAwB;AAAA,QAAlB,SAAkB,uEAAN,IAAM;;AAAA;;AAC1C,SAAK,WAAL,GAAmB,sBAAnB;AACA,SAAK,QAAL,GAAgB,IAAI,KAAK,mBAAT,CAA6B,KAAK,WAAlC,CAAhB;;AAEA;AACA,SAAK,MAAL,GAAc,IAAd;AACA;AACA,SAAK,IAAL,GAAY,IAAZ;AACA;AACA,SAAK,eAAL,GAAuB,IAAvB;;AAEA,SAAK,UAAL,GAAkB,KAAK,MAAL,CAAY,EAAE,QAAQ,IAAV,EAAZ,EAA8B,SAA9B,CAAlB;;AAEA,SAAK,QAAL,CAAc,KAAd;AACD;;AAED;;;;;;;;;;;;;;;;;6BAaS,K,EAAO;AAAA;;AACd;AACA,UAAI,KAAK,MAAL,KAAgB,KAApB,EACE;AACF;AACA,UAAI,CAAC,KAAK,MAAN,IAAgB,CAAC,KAArB,EACE;;AAEF,UAAI,KAAK,IAAT,EAAe;AACb,aAAK,IAAL,CAAU,GAAV,CAAc,QAAd,EAAwB,KAAK,eAA7B;AACA,aAAK,IAAL,GAAY,IAAZ;AACA,aAAK,eAAL,GAAuB,IAAvB;AACD;;AAED,WAAK,MAAL,GAAc,KAAd;;AAEA,UAAI,KAAJ,EAAW;AACT,aAAK,IAAL,GAAY,qBAAI,KAAJ,EAAW,GAAX,CAAe,WAAf,CAAZ;AACA,YAAI,MAAM,KAAK,IAAL,CAAU,EAAV,CAAa,QAAb,EAAuB,UAAC,CAAD,EAAO;AACtC,gBAAK,WAAL,CAAiB,OAAjB,CAAyB,QAAzB,EAAmC,CAAnC;AACD,SAFS,CAAV;AAGA,aAAK,eAAL,GAAuB,GAAvB;AACD;AACF;;AAED;;;;;;;;;;;;;;;AAcA;;;;;oCAKgB,S,EAAW;AACzB;AACA,aAAO,KAAK,MAAL,CAAY,EAAZ,EACL,KAAK,UAAL,GAAkB,KAAK,UAAvB,GAAoC,IAD/B,EAEL,YAAY,SAAZ,GAAwB,IAFnB,CAAP;AAGD;;AAED;;;;;;;;;;;;;;;wBAYI,Y,EAAc,S,EAAW;AAC3B,UAAI,KAAK,IAAT,EACE,KAAK,IAAL,CAAU,GAAV,CAAc,YAAd,EAA4B,KAAK,eAAL,CAAqB,SAArB,CAA5B;AACH;;AAED;;;;;;;;;;;;;0BAUM,S,EAAW;AACf,UAAI,KAAK,IAAT,EACE,KAAK,GAAL,CAAS,KAAK,CAAd,EAAiB,KAAK,eAAL,CAAqB,SAArB,CAAjB;AACH;;AAED;;;;;;;;;;;;;uBAUG,S,EAAW,Q,EAAU;AACtB,aAAO,KAAK,QAAL,CAAc,EAAd,CAAiB,SAAjB,EAA4B,QAA5B,CAAP;AACD;;AAED;;;;;;;;;;;wBAQI,S,EAAW,Q,EAAU;AACvB,aAAO,KAAK,QAAL,CAAc,GAAd,CAAkB,SAAlB,EAA6B,QAA7B,CAAP;AACD;;AAED;;;;;;;;4BAKQ;AACN,WAAK,QAAL,CAAc,kBAAd;AACA,WAAK,QAAL,CAAc,IAAd;AACD;;;wBAlFW;AACV,aAAO,KAAK,IAAL,GAAY,KAAK,IAAL,CAAU,GAAV,EAAZ,GAA8B,IAArC;AACD;;;;;;AAmFH;;;;;;;;;AASA;;;;;;;;;;;;;;;;;;;;;QCpLgB,M,GAAA,M;QAeA,W,GAAA,W;QAQA,e,GAAA,e;QAoCA,a,GAAA,a;;;;AA3DT,SAAS,MAAT,CAAgB,MAAhB,EAAoC;AAAA,oCAAT,OAAS;AAAT,WAAS;AAAA;;AACzC,OAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,QAAQ,MAA5B,EAAoC,GAApC,EAAyC;AACvC,QAAI,MAAM,QAAQ,CAAR,CAAV;AACA,QAAI,OAAO,GAAP,KAAgB,WAAhB,IAA+B,QAAQ,IAA3C,EACE;;AAEF,SAAK,IAAI,GAAT,IAAgB,GAAhB,EAAqB;AACnB,UAAI,IAAI,cAAJ,CAAmB,GAAnB,CAAJ,EAA6B;AAC3B,eAAO,GAAP,IAAc,IAAI,GAAJ,CAAd;AACD;AACF;AACF;AACD,SAAO,MAAP;AACD;;AAEM,SAAS,WAAT,CAAqB,IAArB,EAA2B;AAChC,OAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAzB,EAAiC,GAAjC,EAAsC;AACpC,QAAI,KAAK,CAAL,KAAW,KAAK,IAAE,CAAP,CAAf,EAA0B;AACxB,YAAM,IAAI,KAAJ,CAAU,0CAAV,CAAN;AACD;AACF;AACF;;AAEM,SAAS,eAAT,CAAyB,CAAzB,EAA4B,CAA5B,EAA+B;AACpC,MAAI,MAAM,CAAV;AACA,MAAI,MAAM,CAAV;;AAEA,MAAI,CAAC,CAAL,EAAQ,IAAI,EAAJ;AACR,MAAI,CAAC,CAAL,EAAQ,IAAI,EAAJ;;AAER,MAAI,SAAS,EAAb;AACA,MAAI,SAAS,EAAb;;AAEA,cAAY,CAAZ;AACA,cAAY,CAAZ;;AAEA,SAAO,MAAM,EAAE,MAAR,IAAkB,MAAM,EAAE,MAAjC,EAAyC;AACvC,QAAI,EAAE,GAAF,MAAW,EAAE,GAAF,CAAf,EAAuB;AACrB;AACA;AACD,KAHD,MAGO,IAAI,EAAE,GAAF,IAAS,EAAE,GAAF,CAAb,EAAqB;AAC1B,aAAO,IAAP,CAAY,EAAE,KAAF,CAAZ;AACD,KAFM,MAEA;AACL,aAAO,IAAP,CAAY,EAAE,KAAF,CAAZ;AACD;AACF;;AAED,MAAI,MAAM,EAAE,MAAZ,EACE,SAAS,OAAO,MAAP,CAAc,EAAE,KAAF,CAAQ,GAAR,CAAd,CAAT;AACF,MAAI,MAAM,EAAE,MAAZ,EACE,SAAS,OAAO,MAAP,CAAc,EAAE,KAAF,CAAQ,GAAR,CAAd,CAAT;AACF,SAAO;AACL,aAAS,MADJ;AAEL,WAAO;AAFF,GAAP;AAID;;AAED;AACA;AACO,SAAS,aAAT,CAAuB,EAAvB,EAA2B;AAChC,MAAI,QAAQ,EAAZ;AACA,MAAI,eAAJ;AACA,OAAK,IAAI,IAAT,IAAiB,EAAjB,EAAqB;AACnB,QAAI,GAAG,cAAH,CAAkB,IAAlB,CAAJ,EACE,MAAM,IAAN,CAAW,IAAX;AACF,QAAI,QAAO,GAAG,IAAH,CAAP,MAAqB,QAArB,IAAiC,OAAO,GAAG,IAAH,EAAS,MAAhB,KAA4B,WAAjE,EAA8E;AAC5E,YAAM,IAAI,KAAJ,CAAU,2BAAV,CAAN;AACD,KAFD,MAEO,IAAI,OAAO,MAAP,KAAmB,WAAnB,IAAkC,WAAW,GAAG,IAAH,EAAS,MAA1D,EAAkE;AACvE,YAAM,IAAI,KAAJ,CAAU,8CAAV,CAAN;AACD;AACD,aAAS,GAAG,IAAH,EAAS,MAAlB;AACD;AACD,MAAI,UAAU,EAAd;AACA,MAAI,aAAJ;AACA,OAAK,IAAI,MAAM,CAAf,EAAkB,MAAM,MAAxB,EAAgC,KAAhC,EAAuC;AACrC,WAAO,EAAP;AACA,SAAK,IAAI,MAAM,CAAf,EAAkB,MAAM,MAAM,MAA9B,EAAsC,KAAtC,EAA6C;AAC3C,WAAK,MAAM,GAAN,CAAL,IAAmB,GAAG,MAAM,GAAN,CAAH,EAAe,GAAf,CAAnB;AACD;AACD,YAAQ,IAAR,CAAa,IAAb;AACD;AACD,SAAO,OAAP;AACD;;AAED;;;;;;;IAMa,mB,WAAA,mB;AACX,+BAAY,OAAZ,EAAqB;AAAA;;AACnB,SAAK,QAAL,GAAgB,OAAhB;AACA,SAAK,KAAL,GAAa,EAAb;AACD;;;;uBAEE,S,EAAW,Q,EAAU;AACtB,UAAI,MAAM,KAAK,QAAL,CAAc,EAAd,CAAiB,SAAjB,EAA4B,QAA5B,CAAV;AACA,WAAK,KAAL,CAAW,GAAX,IAAkB,SAAlB;AACA,aAAO,GAAP;AACD;;;wBAEG,S,EAAW,Q,EAAU;AACvB,UAAI,MAAM,KAAK,QAAL,CAAc,GAAd,CAAkB,SAAlB,EAA6B,QAA7B,CAAV;AACA,UAAI,GAAJ,EAAS;AACP,eAAO,KAAK,KAAL,CAAW,GAAX,CAAP;AACD;AACD,aAAO,GAAP;AACD;;;yCAEoB;AAAA;;AACnB,UAAI,eAAe,KAAK,KAAxB;AACA,WAAK,KAAL,GAAa,EAAb;AACA,aAAO,IAAP,CAAY,YAAZ,EAA0B,OAA1B,CAAkC,UAAC,GAAD,EAAS;AACzC,cAAK,QAAL,CAAc,GAAd,CAAkB,aAAa,GAAb,CAAlB,EAAqC,GAArC;AACD,OAFD;AAGD;;;;;;;;;;;;;;;;;;ACpHH;;;;;;;;IAEqB,G;AACnB,eAAY,KAAZ,EAAmB,IAAnB,EAAyB,YAAa,KAAtC,EAA6C;AAAA;;AAC3C,SAAK,MAAL,GAAc,KAAd;AACA,SAAK,KAAL,GAAa,IAAb;AACA,SAAK,MAAL,GAAc,KAAd;AACA,SAAK,OAAL,GAAe,sBAAf;AACD;;;;0BAEK;AACJ,aAAO,KAAK,MAAZ;AACD;;;wBAEG,K,EAAO,YAAa,K,EAAO;AAC7B,UAAI,KAAK,MAAL,KAAgB,KAApB,EAA2B;AACzB;AACA;AACD;AACD,UAAI,WAAW,KAAK,MAApB;AACA,WAAK,MAAL,GAAc,KAAd;AACA;AACA,UAAI,MAAM,EAAV;AACA,UAAI,SAAS,QAAO,KAAP,yCAAO,KAAP,OAAkB,QAA/B,EAAyC;AACvC,aAAK,IAAI,CAAT,IAAc,KAAd,EAAqB;AACnB,cAAI,MAAM,cAAN,CAAqB,CAArB,CAAJ,EACE,IAAI,CAAJ,IAAS,MAAM,CAAN,CAAT;AACH;AACF;AACD,UAAI,QAAJ,GAAe,QAAf;AACA,UAAI,KAAJ,GAAY,KAAZ;AACA,WAAK,OAAL,CAAa,OAAb,CAAqB,QAArB,EAA+B,GAA/B,EAAoC,IAApC;;AAEA;AACA;AACA,UAAI,OAAO,KAAP,IAAgB,OAAO,KAAP,CAAa,aAAjC,EAAgD;AAC9C,eAAO,KAAP,CAAa,aAAb,CACE,mBACG,KAAK,MAAL,CAAY,IAAZ,KAAqB,IAArB,GAA4B,KAAK,MAAL,CAAY,IAAZ,GAAmB,GAA/C,GAAqD,EADxD,IAEE,KAAK,KAHT,EAIE,OAAO,KAAP,KAAkB,WAAlB,GAAgC,IAAhC,GAAuC,KAJzC;AAMD;AACF;;;uBAEE,S,EAAW,Q,EAAU;AACtB,aAAO,KAAK,OAAL,CAAa,EAAb,CAAgB,SAAhB,EAA2B,QAA3B,CAAP;AACD;;;wBAEG,S,EAAW,Q,EAAU;AACvB,aAAO,KAAK,OAAL,CAAa,GAAb,CAAiB,SAAjB,EAA4B,QAA5B,CAAP;AACD;;;;;;kBAjDkB,G", + "file": "generated.js", + "sourceRoot": "", + "sourcesContent": [ + "(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Combine the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Close the handle. This clears this handle's contribution to the filter set,\n * and unsubscribes all event listeners.\n */\n close() {\n this._emitter.removeAllListeners();\n this.clear();\n this.setGroup(null);\n }\n\n /**\n * Clear this handle's contribution to the filter set.\n *\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n clear(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.clear(this._id);\n this._onChange(extraInfo);\n }\n\n /**\n * Set this handle's contribution to the filter set. This array should consist\n * of the keys of the rows that _should_ be displayed; any keys that are not\n * present in the array will be considered _filtered out_. Note that multiple\n * `FilterHandle` instances in the group may each contribute an array of keys,\n * and only those keys that appear in _all_ of the arrays make it through the\n * filter.\n *\n * @param {string[]} keys - Empty array, or array of keys. To clear the\n * filter, don't pass an empty array; instead, use the\n * {@link FilterHandle#clear} method.\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n set(keys, extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.update(this._id, keys);\n this._onChange(extraInfo);\n }\n\n /**\n * @return {string[]|null} - Either: 1) an array of keys that made it through\n * all of the `FilterHandle` instances, or, 2) `null`, which means no filter\n * is being applied (all data should be displayed).\n */\n get filteredKeys() {\n return this._filterSet ? this._filterSet.value : null;\n }\n\n /**\n * Subscribe to events on this `FilterHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {FilterHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link FilterHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancel event subscriptions created by {@link FilterHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|FilterHandle~listener} listener - Either the callback\n * function previously passed into {@link FilterHandle#on}, or the\n * string that was returned from {@link FilterHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n _onChange(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterVar.set(this._filterSet.value, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * @callback FilterHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the filter set, or `null` if no filter set is active),\n * `oldValue` (the previous value of the filter set), and `sender` (the\n * `FilterHandle` instance that made the change).\n */\n\n}\n\n/**\n * @event FilterHandle#change\n * @type {object}\n * @property {object} value - The new value of the filter set, or `null`\n * if no filter set is active.\n * @property {object} oldValue - The previous value of the filter set.\n * @property {FilterHandle} sender - The `FilterHandle` instance that\n * changed the value.\n */\n", + "import { diffSortedLists } from \"./util\";\n\nfunction naturalComparator(a, b) {\n if (a === b) {\n return 0;\n } else if (a < b) {\n return -1;\n } else if (a > b) {\n return 1;\n }\n}\n\n/**\n * @private\n */\nexport default class FilterSet {\n constructor() {\n this.reset();\n }\n\n reset() {\n // Key: handle ID, Value: array of selected keys, or null\n this._handles = {};\n // Key: key string, Value: count of handles that include it\n this._keys = {};\n this._value = null;\n this._activeHandles = 0;\n }\n\n get value() {\n return this._value;\n }\n\n update(handleId, keys) {\n if (keys !== null) {\n keys = keys.slice(0); // clone before sorting\n keys.sort(naturalComparator);\n }\n\n let {added, removed} = diffSortedLists(this._handles[handleId], keys);\n this._handles[handleId] = keys;\n\n for (let i = 0; i < added.length; i++) {\n this._keys[added[i]] = (this._keys[added[i]] || 0) + 1;\n }\n for (let i = 0; i < removed.length; i++) {\n this._keys[removed[i]]--;\n }\n\n this._updateValue(keys);\n }\n\n /**\n * @param {string[]} keys Sorted array of strings that indicate\n * a superset of possible keys.\n * @private\n */\n _updateValue(keys = this._allKeys) {\n let handleCount = Object.keys(this._handles).length;\n if (handleCount === 0) {\n this._value = null;\n } else {\n this._value = [];\n for (let i = 0; i < keys.length; i++) {\n let count = this._keys[keys[i]];\n if (count === handleCount) {\n this._value.push(keys[i]);\n }\n }\n }\n }\n\n clear(handleId) {\n if (typeof(this._handles[handleId]) === \"undefined\") {\n return;\n }\n\n let keys = this._handles[handleId];\n if (!keys) {\n keys = [];\n }\n\n for (let i = 0; i < keys.length; i++) {\n this._keys[keys[i]]--;\n }\n delete this._handles[handleId];\n\n this._updateValue();\n }\n\n get _allKeys() {\n let allKeys = Object.keys(this._keys);\n allKeys.sort(naturalComparator);\n return allKeys;\n }\n}\n", + "import Var from \"./var\";\n\n// Use a global so that multiple copies of crosstalk.js can be loaded and still\n// have groups behave as singletons across all copies.\nglobal.__crosstalk_groups = global.__crosstalk_groups || {};\nlet groups = global.__crosstalk_groups;\n\nexport default function group(groupName) {\n if (groupName && typeof(groupName) === \"string\") {\n if (!groups.hasOwnProperty(groupName)) {\n groups[groupName] = new Group(groupName);\n }\n return groups[groupName];\n } else if (typeof(groupName) === \"object\" && groupName._vars && groupName.var) {\n // Appears to already be a group object\n return groupName;\n } else if (Array.isArray(groupName) &&\n groupName.length == 1 &&\n typeof(groupName[0]) === \"string\") {\n return group(groupName[0]);\n } else {\n throw new Error(\"Invalid groupName argument\");\n }\n}\n\nclass Group {\n constructor(name) {\n this.name = name;\n this._vars = {};\n }\n\n var(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n if (!this._vars.hasOwnProperty(name))\n this._vars[name] = new Var(this, name);\n return this._vars[name];\n }\n\n has(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n return this._vars.hasOwnProperty(name);\n }\n}\n", + "import group from \"./group\";\nimport { SelectionHandle } from \"./selection\";\nimport { FilterHandle } from \"./filter\";\nimport { bind } from \"./input\";\nimport \"./input_selectize\";\nimport \"./input_checkboxgroup\";\nimport \"./input_slider\";\n\nconst defaultGroup = group(\"default\");\n\nfunction var_(name) {\n return defaultGroup.var(name);\n}\n\nfunction has(name) {\n return defaultGroup.has(name);\n}\n\nif (global.Shiny) {\n global.Shiny.addCustomMessageHandler(\"update-client-value\", function(message) {\n if (typeof(message.group) === \"string\") {\n group(message.group).var(message.name).set(message.value);\n } else {\n var_(message.name).set(message.value);\n }\n });\n}\n\nconst crosstalk = {\n group: group,\n var: var_,\n has: has,\n SelectionHandle: SelectionHandle,\n FilterHandle: FilterHandle,\n bind: bind\n};\n\n/**\n * @namespace crosstalk\n */\nexport default crosstalk;\nglobal.crosstalk = crosstalk;\n", + "let $ = global.jQuery;\n\nlet bindings = {};\n\nexport function register(reg) {\n bindings[reg.className] = reg;\n if (global.document && global.document.readyState !== \"complete\") {\n $(() => {\n bind();\n });\n } else if (global.document) {\n setTimeout(bind, 100);\n }\n}\n\nexport function bind() {\n Object.keys(bindings).forEach(function(className) {\n let binding = bindings[className];\n $(\".\" + binding.className).not(\".crosstalk-input-bound\").each(function(i, el) {\n bindInstance(binding, el);\n });\n });\n}\n\n// Escape jQuery identifier\nfunction $escape(val) {\n return val.replace(/([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~])/g, \"\\\\$1\");\n}\n\nfunction bindEl(el) {\n let $el = $(el);\n Object.keys(bindings).forEach(function(className) {\n if ($el.hasClass(className) && !$el.hasClass(\"crosstalk-input-bound\")) {\n let binding = bindings[className];\n bindInstance(binding, el);\n }\n });\n}\n\nfunction bindInstance(binding, el) {\n let jsonEl = $(el).find(\"script[type='application/json'][data-for='\" + $escape(el.id) + \"']\");\n let data = JSON.parse(jsonEl[0].innerText);\n\n let instance = binding.factory(el, data);\n $(el).data(\"crosstalk-instance\", instance);\n $(el).addClass(\"crosstalk-input-bound\");\n}\n\nif (global.Shiny) {\n let inputBinding = new global.Shiny.InputBinding();\n let $ = global.jQuery;\n $.extend(inputBinding, {\n find: function(scope) {\n return $(scope).find(\".crosstalk-input\");\n },\n initialize: function(el) {\n if (!$(el).hasClass(\"crosstalk-input-bound\")) {\n bindEl(el);\n }\n },\n getId: function(el) {\n return el.id;\n },\n getValue: function(el) {\n\n },\n setValue: function(el, value) {\n\n },\n receiveMessage: function(el, data) {\n\n },\n subscribe: function(el, callback) {\n $(el).data(\"crosstalk-instance\").resume();\n },\n unsubscribe: function(el) {\n $(el).data(\"crosstalk-instance\").suspend();\n }\n });\n global.Shiny.inputBindings.register(inputBinding, \"crosstalk.inputBinding\");\n}\n", + "import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-checkboxgroup\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n let $el = $(el);\n $el.on(\"change\", \"input[type='checkbox']\", function() {\n let checked = $el.find(\"input[type='checkbox']:checked\");\n if (checked.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n checked.each(function() {\n data.map[this.value].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n", + "import * as input from \"./input\";\nimport * as util from \"./util\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-select\",\n\n factory: function(el, data) {\n /*\n * items: {value: [...], label: [...]}\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n\n let first = [{value: \"\", label: \"(All)\"}];\n let items = util.dataframeToD3(data.items);\n let opts = {\n options: first.concat(items),\n valueField: \"value\",\n labelField: \"label\",\n searchField: \"label\"\n };\n\n let select = $(el).find(\"select\")[0];\n\n let selectize = $(select).selectize(opts)[0].selectize;\n\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n selectize.on(\"change\", function() {\n if (selectize.items.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n selectize.items.forEach(function(group) {\n data.map[group].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n", + "import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\nlet strftime = global.strftime;\n\ninput.register({\n className: \"crosstalk-input-slider\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let opts = {};\n let $el = $(el).find(\"input\");\n let dataType = $el.data(\"data-type\");\n let timeFormat = $el.data(\"time-format\");\n let round = $el.data(\"round\");\n let timeFormatter;\n\n // Set up formatting functions\n if (dataType === \"date\") {\n timeFormatter = strftime.utc();\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n\n } else if (dataType === \"datetime\") {\n let timezone = $el.data(\"timezone\");\n if (timezone)\n timeFormatter = strftime.timezone(timezone);\n else\n timeFormatter = strftime;\n\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n } else if (dataType === \"number\") {\n if (typeof round !== \"undefined\")\n opts.prettify = function(num) {\n let factor = Math.pow(10, round);\n return Math.round(num * factor) / factor;\n };\n }\n\n $el.ionRangeSlider(opts);\n\n function getValue() {\n let result = $el.data(\"ionRangeSlider\").result;\n\n // Function for converting numeric value from slider to appropriate type.\n let convert;\n let dataType = $el.data(\"data-type\");\n if (dataType === \"date\") {\n convert = function(val) {\n return formatDateUTC(new Date(+val));\n };\n } else if (dataType === \"datetime\") {\n convert = function(val) {\n // Convert ms to s\n return +val / 1000;\n };\n } else {\n convert = function(val) { return +val; };\n }\n\n if ($el.data(\"ionRangeSlider\").options.type === \"double\") {\n return [convert(result.from), convert(result.to)];\n } else {\n return convert(result.from);\n }\n }\n\n let lastKnownKeys = null;\n\n $el.on(\"change.crosstalkSliderInput\", function(event) {\n if (!$el.data(\"updating\") && !$el.data(\"animating\")) {\n let [from, to] = getValue();\n let keys = [];\n for (let i = 0; i < data.values.length; i++) {\n let val = data.values[i];\n if (val >= from && val <= to) {\n keys.push(data.keys[i]);\n }\n }\n keys.sort();\n ctHandle.set(keys);\n lastKnownKeys = keys;\n }\n });\n\n\n // let $el = $(el);\n // $el.on(\"change\", \"input[type=\"checkbox\"]\", function() {\n // let checked = $el.find(\"input[type=\"checkbox\"]:checked\");\n // if (checked.length === 0) {\n // ctHandle.clear();\n // } else {\n // let keys = {};\n // checked.each(function() {\n // data.map[this.value].forEach(function(key) {\n // keys[key] = true;\n // });\n // });\n // let keyArray = Object.keys(keys);\n // keyArray.sort();\n // ctHandle.set(keyArray);\n // }\n // });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n\n\n// Convert a number to a string with leading zeros\nfunction padZeros(n, digits) {\n let str = n.toString();\n while (str.length < digits)\n str = \"0\" + str;\n return str;\n}\n\n// Given a Date object, return a string in yyyy-mm-dd format, using the\n// UTC date. This may be a day off from the date in the local time zone.\nfunction formatDateUTC(date) {\n if (date instanceof Date) {\n return date.getUTCFullYear() + \"-\" +\n padZeros(date.getUTCMonth()+1, 2) + \"-\" +\n padZeros(date.getUTCDate(), 2);\n\n } else {\n return null;\n }\n}\n", + "import Events from \"./events\";\nimport grp from \"./group\";\nimport * as util from \"./util\";\n\n/**\n * Use this class to read and write (and listen for changes to) the selection\n * for a Crosstalk group. This is intended to be used for linked brushing.\n *\n * If two (or more) `SelectionHandle` instances in the same webpage share the\n * same group name, they will share the same state. Setting the selection using\n * one `SelectionHandle` instance will result in the `value` property instantly\n * changing across the others, and `\"change\"` event listeners on all instances\n * (including the one that initiated the sending) will fire.\n *\n * @param {string} [group] - The name of the Crosstalk group, or if none,\n * null or undefined (or any other falsy value). This can be changed later\n * via the [SelectionHandle#setGroup](#setGroup) method.\n * @param {Object} [extraInfo] - An object whose properties will be copied to\n * the event object whenever an event is emitted.\n */\nexport class SelectionHandle {\n\n constructor(group = null, extraInfo = null) {\n this._eventRelay = new Events();\n this._emitter = new util.SubscriptionTracker(this._eventRelay);\n\n // Name of the group we're currently tracking, if any. Can change over time.\n this._group = null;\n // The Var we're currently tracking, if any. Can change over time.\n this._var = null;\n // The event handler subscription we currently have on var.on(\"change\").\n this._varOnChangeSub = null;\n\n this._extraInfo = util.extend({ sender: this }, extraInfo);\n\n this.setGroup(group);\n }\n\n /**\n * Changes the Crosstalk group membership of this SelectionHandle. The group\n * being switched away from (if any) will not have its selection value\n * modified as a result of calling `setGroup`, even if this handle was the\n * most recent handle to set the selection of the group.\n *\n * The group being switched to (if any) will also not have its selection value\n * modified as a result of calling `setGroup`. If you want to set the\n * selection value of the new group, call `set` explicitly.\n *\n * @param {string} group - The name of the Crosstalk group, or null (or\n * undefined) to clear the group.\n */\n setGroup(group) {\n // If group is unchanged, do nothing\n if (this._group === group)\n return;\n // Treat null, undefined, and other falsy values the same\n if (!this._group && !group)\n return;\n\n if (this._var) {\n this._var.off(\"change\", this._varOnChangeSub);\n this._var = null;\n this._varOnChangeSub = null;\n }\n\n this._group = group;\n\n if (group) {\n this._var = grp(group).var(\"selection\");\n let sub = this._var.on(\"change\", (e) => {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Retrieves the current selection for the group represented by this\n * `SelectionHandle`.\n *\n * - If no selection is active, then this value will be falsy.\n * - If a selection is active, but no data points are selected, then this\n * value will be an empty array.\n * - If a selection is active, and data points are selected, then the keys\n * of the selected data points will be present in the array.\n */\n get value() {\n return this._var ? this._var.get() : null;\n }\n\n /**\n * Combines the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n // Important incidental effect: shallow clone is returned\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {string[]} selectedKeys - Falsy, empty array, or array of keys (see\n * {@link SelectionHandle#value}).\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `SelectionHandle` constructor).\n */\n set(selectedKeys, extraInfo) {\n if (this._var)\n this._var.set(selectedKeys, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any that were passed\n * into the `SelectionHandle` constructor).\n */\n clear(extraInfo) {\n if (this._var)\n this.set(void 0, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Subscribes to events on this `SelectionHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {SelectionHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link SelectionHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancels event subscriptions created by {@link SelectionHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|SelectionHandle~listener} listener - Either the callback\n * function previously passed into {@link SelectionHandle#on}, or the\n * string that was returned from {@link SelectionHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n /**\n * Shuts down the `SelectionHandle` object.\n *\n * Removes all event listeners that were added through this handle.\n */\n close() {\n this._emitter.removeAllListeners();\n this.setGroup(null);\n }\n}\n\n/**\n * @callback SelectionHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the selection, or `undefined` if no selection is active),\n * `oldValue` (the previous value of the selection), and `sender` (the\n * `SelectionHandle` instance that made the change).\n */\n\n/**\n * @event SelectionHandle#change\n * @type {object}\n * @property {object} value - The new value of the selection, or `undefined`\n * if no selection is active.\n * @property {object} oldValue - The previous value of the selection.\n * @property {SelectionHandle} sender - The `SelectionHandle` instance that\n * changed the value.\n */\n", + "export function extend(target, ...sources) {\n for (let i = 0; i < sources.length; i++) {\n let src = sources[i];\n if (typeof(src) === \"undefined\" || src === null)\n continue;\n\n for (let key in src) {\n if (src.hasOwnProperty(key)) {\n target[key] = src[key];\n }\n }\n }\n return target;\n}\n\nexport function checkSorted(list) {\n for (let i = 1; i < list.length; i++) {\n if (list[i] <= list[i-1]) {\n throw new Error(\"List is not sorted or contains duplicate\");\n }\n }\n}\n\nexport function diffSortedLists(a, b) {\n let i_a = 0;\n let i_b = 0;\n\n if (!a) a = [];\n if (!b) b = [];\n\n let a_only = [];\n let b_only = [];\n\n checkSorted(a);\n checkSorted(b);\n\n while (i_a < a.length && i_b < b.length) {\n if (a[i_a] === b[i_b]) {\n i_a++;\n i_b++;\n } else if (a[i_a] < b[i_b]) {\n a_only.push(a[i_a++]);\n } else {\n b_only.push(b[i_b++]);\n }\n }\n\n if (i_a < a.length)\n a_only = a_only.concat(a.slice(i_a));\n if (i_b < b.length)\n b_only = b_only.concat(b.slice(i_b));\n return {\n removed: a_only,\n added: b_only\n };\n}\n\n// Convert from wide: { colA: [1,2,3], colB: [4,5,6], ... }\n// to long: [ {colA: 1, colB: 4}, {colA: 2, colB: 5}, ... ]\nexport function dataframeToD3(df) {\n let names = [];\n let length;\n for (let name in df) {\n if (df.hasOwnProperty(name))\n names.push(name);\n if (typeof(df[name]) !== \"object\" || typeof(df[name].length) === \"undefined\") {\n throw new Error(\"All fields must be arrays\");\n } else if (typeof(length) !== \"undefined\" && length !== df[name].length) {\n throw new Error(\"All fields must be arrays of the same length\");\n }\n length = df[name].length;\n }\n let results = [];\n let item;\n for (let row = 0; row < length; row++) {\n item = {};\n for (let col = 0; col < names.length; col++) {\n item[names[col]] = df[names[col]][row];\n }\n results.push(item);\n }\n return results;\n}\n\n/**\n * Keeps track of all event listener additions/removals and lets all active\n * listeners be removed with a single operation.\n *\n * @private\n */\nexport class SubscriptionTracker {\n constructor(emitter) {\n this._emitter = emitter;\n this._subs = {};\n }\n\n on(eventType, listener) {\n let sub = this._emitter.on(eventType, listener);\n this._subs[sub] = eventType;\n return sub;\n }\n\n off(eventType, listener) {\n let sub = this._emitter.off(eventType, listener);\n if (sub) {\n delete this._subs[sub];\n }\n return sub;\n }\n\n removeAllListeners() {\n let current_subs = this._subs;\n this._subs = {};\n Object.keys(current_subs).forEach((sub) => {\n this._emitter.off(current_subs[sub], sub);\n });\n }\n}\n", + "import Events from \"./events\";\n\nexport default class Var {\n constructor(group, name, /*optional*/ value) {\n this._group = group;\n this._name = name;\n this._value = value;\n this._events = new Events();\n }\n\n get() {\n return this._value;\n }\n\n set(value, /*optional*/ event) {\n if (this._value === value) {\n // Do nothing; the value hasn't changed\n return;\n }\n let oldValue = this._value;\n this._value = value;\n // Alert JavaScript listeners that the value has changed\n let evt = {};\n if (event && typeof(event) === \"object\") {\n for (let k in event) {\n if (event.hasOwnProperty(k))\n evt[k] = event[k];\n }\n }\n evt.oldValue = oldValue;\n evt.value = value;\n this._events.trigger(\"change\", evt, this);\n\n // TODO: Make this extensible, to let arbitrary back-ends know that\n // something has changed\n if (global.Shiny && global.Shiny.onInputChange) {\n global.Shiny.onInputChange(\n \".clientValue-\" +\n (this._group.name !== null ? this._group.name + \"-\" : \"\") +\n this._name,\n typeof(value) === \"undefined\" ? null : value\n );\n }\n }\n\n on(eventType, listener) {\n return this._events.on(eventType, listener);\n }\n\n off(eventType, listener) {\n return this._events.off(eventType, listener);\n }\n}\n" + ] +} \ No newline at end of file diff --git a/docs/site_libs/crosstalk-1.2.1/js/crosstalk.min.js b/docs/site_libs/crosstalk-1.2.1/js/crosstalk.min.js new file mode 100644 index 000000000..b7ec0ac9f --- /dev/null +++ b/docs/site_libs/crosstalk-1.2.1/js/crosstalk.min.js @@ -0,0 +1,2 @@ +!function o(u,a,l){function s(n,e){if(!a[n]){if(!u[n]){var t="function"==typeof require&&require;if(!e&&t)return t(n,!0);if(f)return f(n,!0);var r=new Error("Cannot find module '"+n+"'");throw r.code="MODULE_NOT_FOUND",r}var i=a[n]={exports:{}};u[n][0].call(i.exports,function(e){var t=u[n][1][e];return s(t||e)},i,i.exports,o,u,a,l)}return a[n].exports}for(var f="function"==typeof require&&require,e=0;e?@[\\\]^`{|}~])/g,"\\$1")+"']"),r=JSON.parse(n[0].innerText),i=e.factory(t,r);o(t).data("crosstalk-instance",i),o(t).addClass("crosstalk-input-bound")}if(t.Shiny){var e=new t.Shiny.InputBinding,u=t.jQuery;u.extend(e,{find:function(e){return u(e).find(".crosstalk-input")},initialize:function(e){var t,n;u(e).hasClass("crosstalk-input-bound")||(n=o(t=e),Object.keys(r).forEach(function(e){n.hasClass(e)&&!n.hasClass("crosstalk-input-bound")&&i(r[e],t)}))},getId:function(e){return e.id},getValue:function(e){},setValue:function(e,t){},receiveMessage:function(e,t){},subscribe:function(e,t){u(e).data("crosstalk-instance").resume()},unsubscribe:function(e){u(e).data("crosstalk-instance").suspend()}}),t.Shiny.inputBindings.register(e,"crosstalk.inputBinding")}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],7:[function(r,e,t){(function(e){"use strict";var t=function(e){{if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}}(r("./input")),n=r("./filter");var a=e.jQuery;t.register({className:"crosstalk-input-checkboxgroup",factory:function(e,r){var i=new n.FilterHandle(r.group),o=void 0,u=a(e);return u.on("change","input[type='checkbox']",function(){var e=u.find("input[type='checkbox']:checked");if(0===e.length)o=null,i.clear();else{var t={};e.each(function(){r.map[this.value].forEach(function(e){t[e]=!0})});var n=Object.keys(t);n.sort(),o=n,i.set(n)}}),{suspend:function(){i.clear()},resume:function(){o&&i.set(o)}}}})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./filter":2,"./input":6}],8:[function(r,e,t){(function(e){"use strict";var t=n(r("./input")),l=n(r("./util")),s=r("./filter");function n(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}var f=e.jQuery;t.register({className:"crosstalk-input-select",factory:function(e,n){var t=l.dataframeToD3(n.items),r={options:[{value:"",label:"(All)"}].concat(t),valueField:"value",labelField:"label",searchField:"label"},i=f(e).find("select")[0],o=f(i).selectize(r)[0].selectize,u=new s.FilterHandle(n.group),a=void 0;return o.on("change",function(){if(0===o.items.length)a=null,u.clear();else{var t={};o.items.forEach(function(e){n.map[e].forEach(function(e){t[e]=!0})});var e=Object.keys(t);e.sort(),a=e,u.set(e)}}),{suspend:function(){u.clear()},resume:function(){a&&u.set(a)}}}})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./filter":2,"./input":6,"./util":11}],9:[function(n,e,t){(function(e){"use strict";var d=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,i=!1,o=void 0;try{for(var u,a=e[Symbol.iterator]();!(r=(u=a.next()).done)&&(n.push(u.value),!t||n.length!==t);r=!0);}catch(e){i=!0,o=e}finally{try{!r&&a.return&&a.return()}finally{if(i)throw o}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},t=function(e){{if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}}(n("./input")),a=n("./filter");var v=e.jQuery,p=e.strftime;function y(e,t){for(var n=e.toString();n.length {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Combine the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Close the handle. This clears this handle's contribution to the filter set,\n * and unsubscribes all event listeners.\n */\n close() {\n this._emitter.removeAllListeners();\n this.clear();\n this.setGroup(null);\n }\n\n /**\n * Clear this handle's contribution to the filter set.\n *\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n clear(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.clear(this._id);\n this._onChange(extraInfo);\n }\n\n /**\n * Set this handle's contribution to the filter set. This array should consist\n * of the keys of the rows that _should_ be displayed; any keys that are not\n * present in the array will be considered _filtered out_. Note that multiple\n * `FilterHandle` instances in the group may each contribute an array of keys,\n * and only those keys that appear in _all_ of the arrays make it through the\n * filter.\n *\n * @param {string[]} keys - Empty array, or array of keys. To clear the\n * filter, don't pass an empty array; instead, use the\n * {@link FilterHandle#clear} method.\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n set(keys, extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.update(this._id, keys);\n this._onChange(extraInfo);\n }\n\n /**\n * @return {string[]|null} - Either: 1) an array of keys that made it through\n * all of the `FilterHandle` instances, or, 2) `null`, which means no filter\n * is being applied (all data should be displayed).\n */\n get filteredKeys() {\n return this._filterSet ? this._filterSet.value : null;\n }\n\n /**\n * Subscribe to events on this `FilterHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {FilterHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link FilterHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancel event subscriptions created by {@link FilterHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|FilterHandle~listener} listener - Either the callback\n * function previously passed into {@link FilterHandle#on}, or the\n * string that was returned from {@link FilterHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n _onChange(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterVar.set(this._filterSet.value, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * @callback FilterHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the filter set, or `null` if no filter set is active),\n * `oldValue` (the previous value of the filter set), and `sender` (the\n * `FilterHandle` instance that made the change).\n */\n\n}\n\n/**\n * @event FilterHandle#change\n * @type {object}\n * @property {object} value - The new value of the filter set, or `null`\n * if no filter set is active.\n * @property {object} oldValue - The previous value of the filter set.\n * @property {FilterHandle} sender - The `FilterHandle` instance that\n * changed the value.\n */\n","import { diffSortedLists } from \"./util\";\n\nfunction naturalComparator(a, b) {\n if (a === b) {\n return 0;\n } else if (a < b) {\n return -1;\n } else if (a > b) {\n return 1;\n }\n}\n\n/**\n * @private\n */\nexport default class FilterSet {\n constructor() {\n this.reset();\n }\n\n reset() {\n // Key: handle ID, Value: array of selected keys, or null\n this._handles = {};\n // Key: key string, Value: count of handles that include it\n this._keys = {};\n this._value = null;\n this._activeHandles = 0;\n }\n\n get value() {\n return this._value;\n }\n\n update(handleId, keys) {\n if (keys !== null) {\n keys = keys.slice(0); // clone before sorting\n keys.sort(naturalComparator);\n }\n\n let {added, removed} = diffSortedLists(this._handles[handleId], keys);\n this._handles[handleId] = keys;\n\n for (let i = 0; i < added.length; i++) {\n this._keys[added[i]] = (this._keys[added[i]] || 0) + 1;\n }\n for (let i = 0; i < removed.length; i++) {\n this._keys[removed[i]]--;\n }\n\n this._updateValue(keys);\n }\n\n /**\n * @param {string[]} keys Sorted array of strings that indicate\n * a superset of possible keys.\n * @private\n */\n _updateValue(keys = this._allKeys) {\n let handleCount = Object.keys(this._handles).length;\n if (handleCount === 0) {\n this._value = null;\n } else {\n this._value = [];\n for (let i = 0; i < keys.length; i++) {\n let count = this._keys[keys[i]];\n if (count === handleCount) {\n this._value.push(keys[i]);\n }\n }\n }\n }\n\n clear(handleId) {\n if (typeof(this._handles[handleId]) === \"undefined\") {\n return;\n }\n\n let keys = this._handles[handleId];\n if (!keys) {\n keys = [];\n }\n\n for (let i = 0; i < keys.length; i++) {\n this._keys[keys[i]]--;\n }\n delete this._handles[handleId];\n\n this._updateValue();\n }\n\n get _allKeys() {\n let allKeys = Object.keys(this._keys);\n allKeys.sort(naturalComparator);\n return allKeys;\n }\n}\n","import Var from \"./var\";\n\n// Use a global so that multiple copies of crosstalk.js can be loaded and still\n// have groups behave as singletons across all copies.\nglobal.__crosstalk_groups = global.__crosstalk_groups || {};\nlet groups = global.__crosstalk_groups;\n\nexport default function group(groupName) {\n if (groupName && typeof(groupName) === \"string\") {\n if (!groups.hasOwnProperty(groupName)) {\n groups[groupName] = new Group(groupName);\n }\n return groups[groupName];\n } else if (typeof(groupName) === \"object\" && groupName._vars && groupName.var) {\n // Appears to already be a group object\n return groupName;\n } else if (Array.isArray(groupName) &&\n groupName.length == 1 &&\n typeof(groupName[0]) === \"string\") {\n return group(groupName[0]);\n } else {\n throw new Error(\"Invalid groupName argument\");\n }\n}\n\nclass Group {\n constructor(name) {\n this.name = name;\n this._vars = {};\n }\n\n var(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n if (!this._vars.hasOwnProperty(name))\n this._vars[name] = new Var(this, name);\n return this._vars[name];\n }\n\n has(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n return this._vars.hasOwnProperty(name);\n }\n}\n","import group from \"./group\";\nimport { SelectionHandle } from \"./selection\";\nimport { FilterHandle } from \"./filter\";\nimport { bind } from \"./input\";\nimport \"./input_selectize\";\nimport \"./input_checkboxgroup\";\nimport \"./input_slider\";\n\nconst defaultGroup = group(\"default\");\n\nfunction var_(name) {\n return defaultGroup.var(name);\n}\n\nfunction has(name) {\n return defaultGroup.has(name);\n}\n\nif (global.Shiny) {\n global.Shiny.addCustomMessageHandler(\"update-client-value\", function(message) {\n if (typeof(message.group) === \"string\") {\n group(message.group).var(message.name).set(message.value);\n } else {\n var_(message.name).set(message.value);\n }\n });\n}\n\nconst crosstalk = {\n group: group,\n var: var_,\n has: has,\n SelectionHandle: SelectionHandle,\n FilterHandle: FilterHandle,\n bind: bind\n};\n\n/**\n * @namespace crosstalk\n */\nexport default crosstalk;\nglobal.crosstalk = crosstalk;\n","let $ = global.jQuery;\n\nlet bindings = {};\n\nexport function register(reg) {\n bindings[reg.className] = reg;\n if (global.document && global.document.readyState !== \"complete\") {\n $(() => {\n bind();\n });\n } else if (global.document) {\n setTimeout(bind, 100);\n }\n}\n\nexport function bind() {\n Object.keys(bindings).forEach(function(className) {\n let binding = bindings[className];\n $(\".\" + binding.className).not(\".crosstalk-input-bound\").each(function(i, el) {\n bindInstance(binding, el);\n });\n });\n}\n\n// Escape jQuery identifier\nfunction $escape(val) {\n return val.replace(/([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~])/g, \"\\\\$1\");\n}\n\nfunction bindEl(el) {\n let $el = $(el);\n Object.keys(bindings).forEach(function(className) {\n if ($el.hasClass(className) && !$el.hasClass(\"crosstalk-input-bound\")) {\n let binding = bindings[className];\n bindInstance(binding, el);\n }\n });\n}\n\nfunction bindInstance(binding, el) {\n let jsonEl = $(el).find(\"script[type='application/json'][data-for='\" + $escape(el.id) + \"']\");\n let data = JSON.parse(jsonEl[0].innerText);\n\n let instance = binding.factory(el, data);\n $(el).data(\"crosstalk-instance\", instance);\n $(el).addClass(\"crosstalk-input-bound\");\n}\n\nif (global.Shiny) {\n let inputBinding = new global.Shiny.InputBinding();\n let $ = global.jQuery;\n $.extend(inputBinding, {\n find: function(scope) {\n return $(scope).find(\".crosstalk-input\");\n },\n initialize: function(el) {\n if (!$(el).hasClass(\"crosstalk-input-bound\")) {\n bindEl(el);\n }\n },\n getId: function(el) {\n return el.id;\n },\n getValue: function(el) {\n\n },\n setValue: function(el, value) {\n\n },\n receiveMessage: function(el, data) {\n\n },\n subscribe: function(el, callback) {\n $(el).data(\"crosstalk-instance\").resume();\n },\n unsubscribe: function(el) {\n $(el).data(\"crosstalk-instance\").suspend();\n }\n });\n global.Shiny.inputBindings.register(inputBinding, \"crosstalk.inputBinding\");\n}\n","import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-checkboxgroup\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n let $el = $(el);\n $el.on(\"change\", \"input[type='checkbox']\", function() {\n let checked = $el.find(\"input[type='checkbox']:checked\");\n if (checked.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n checked.each(function() {\n data.map[this.value].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n","import * as input from \"./input\";\nimport * as util from \"./util\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-select\",\n\n factory: function(el, data) {\n /*\n * items: {value: [...], label: [...]}\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n\n let first = [{value: \"\", label: \"(All)\"}];\n let items = util.dataframeToD3(data.items);\n let opts = {\n options: first.concat(items),\n valueField: \"value\",\n labelField: \"label\",\n searchField: \"label\"\n };\n\n let select = $(el).find(\"select\")[0];\n\n let selectize = $(select).selectize(opts)[0].selectize;\n\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n selectize.on(\"change\", function() {\n if (selectize.items.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n selectize.items.forEach(function(group) {\n data.map[group].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n","import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\nlet strftime = global.strftime;\n\ninput.register({\n className: \"crosstalk-input-slider\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let opts = {};\n let $el = $(el).find(\"input\");\n let dataType = $el.data(\"data-type\");\n let timeFormat = $el.data(\"time-format\");\n let round = $el.data(\"round\");\n let timeFormatter;\n\n // Set up formatting functions\n if (dataType === \"date\") {\n timeFormatter = strftime.utc();\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n\n } else if (dataType === \"datetime\") {\n let timezone = $el.data(\"timezone\");\n if (timezone)\n timeFormatter = strftime.timezone(timezone);\n else\n timeFormatter = strftime;\n\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n } else if (dataType === \"number\") {\n if (typeof round !== \"undefined\")\n opts.prettify = function(num) {\n let factor = Math.pow(10, round);\n return Math.round(num * factor) / factor;\n };\n }\n\n $el.ionRangeSlider(opts);\n\n function getValue() {\n let result = $el.data(\"ionRangeSlider\").result;\n\n // Function for converting numeric value from slider to appropriate type.\n let convert;\n let dataType = $el.data(\"data-type\");\n if (dataType === \"date\") {\n convert = function(val) {\n return formatDateUTC(new Date(+val));\n };\n } else if (dataType === \"datetime\") {\n convert = function(val) {\n // Convert ms to s\n return +val / 1000;\n };\n } else {\n convert = function(val) { return +val; };\n }\n\n if ($el.data(\"ionRangeSlider\").options.type === \"double\") {\n return [convert(result.from), convert(result.to)];\n } else {\n return convert(result.from);\n }\n }\n\n let lastKnownKeys = null;\n\n $el.on(\"change.crosstalkSliderInput\", function(event) {\n if (!$el.data(\"updating\") && !$el.data(\"animating\")) {\n let [from, to] = getValue();\n let keys = [];\n for (let i = 0; i < data.values.length; i++) {\n let val = data.values[i];\n if (val >= from && val <= to) {\n keys.push(data.keys[i]);\n }\n }\n keys.sort();\n ctHandle.set(keys);\n lastKnownKeys = keys;\n }\n });\n\n\n // let $el = $(el);\n // $el.on(\"change\", \"input[type=\"checkbox\"]\", function() {\n // let checked = $el.find(\"input[type=\"checkbox\"]:checked\");\n // if (checked.length === 0) {\n // ctHandle.clear();\n // } else {\n // let keys = {};\n // checked.each(function() {\n // data.map[this.value].forEach(function(key) {\n // keys[key] = true;\n // });\n // });\n // let keyArray = Object.keys(keys);\n // keyArray.sort();\n // ctHandle.set(keyArray);\n // }\n // });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n\n\n// Convert a number to a string with leading zeros\nfunction padZeros(n, digits) {\n let str = n.toString();\n while (str.length < digits)\n str = \"0\" + str;\n return str;\n}\n\n// Given a Date object, return a string in yyyy-mm-dd format, using the\n// UTC date. This may be a day off from the date in the local time zone.\nfunction formatDateUTC(date) {\n if (date instanceof Date) {\n return date.getUTCFullYear() + \"-\" +\n padZeros(date.getUTCMonth()+1, 2) + \"-\" +\n padZeros(date.getUTCDate(), 2);\n\n } else {\n return null;\n }\n}\n","import Events from \"./events\";\nimport grp from \"./group\";\nimport * as util from \"./util\";\n\n/**\n * Use this class to read and write (and listen for changes to) the selection\n * for a Crosstalk group. This is intended to be used for linked brushing.\n *\n * If two (or more) `SelectionHandle` instances in the same webpage share the\n * same group name, they will share the same state. Setting the selection using\n * one `SelectionHandle` instance will result in the `value` property instantly\n * changing across the others, and `\"change\"` event listeners on all instances\n * (including the one that initiated the sending) will fire.\n *\n * @param {string} [group] - The name of the Crosstalk group, or if none,\n * null or undefined (or any other falsy value). This can be changed later\n * via the [SelectionHandle#setGroup](#setGroup) method.\n * @param {Object} [extraInfo] - An object whose properties will be copied to\n * the event object whenever an event is emitted.\n */\nexport class SelectionHandle {\n\n constructor(group = null, extraInfo = null) {\n this._eventRelay = new Events();\n this._emitter = new util.SubscriptionTracker(this._eventRelay);\n\n // Name of the group we're currently tracking, if any. Can change over time.\n this._group = null;\n // The Var we're currently tracking, if any. Can change over time.\n this._var = null;\n // The event handler subscription we currently have on var.on(\"change\").\n this._varOnChangeSub = null;\n\n this._extraInfo = util.extend({ sender: this }, extraInfo);\n\n this.setGroup(group);\n }\n\n /**\n * Changes the Crosstalk group membership of this SelectionHandle. The group\n * being switched away from (if any) will not have its selection value\n * modified as a result of calling `setGroup`, even if this handle was the\n * most recent handle to set the selection of the group.\n *\n * The group being switched to (if any) will also not have its selection value\n * modified as a result of calling `setGroup`. If you want to set the\n * selection value of the new group, call `set` explicitly.\n *\n * @param {string} group - The name of the Crosstalk group, or null (or\n * undefined) to clear the group.\n */\n setGroup(group) {\n // If group is unchanged, do nothing\n if (this._group === group)\n return;\n // Treat null, undefined, and other falsy values the same\n if (!this._group && !group)\n return;\n\n if (this._var) {\n this._var.off(\"change\", this._varOnChangeSub);\n this._var = null;\n this._varOnChangeSub = null;\n }\n\n this._group = group;\n\n if (group) {\n this._var = grp(group).var(\"selection\");\n let sub = this._var.on(\"change\", (e) => {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Retrieves the current selection for the group represented by this\n * `SelectionHandle`.\n *\n * - If no selection is active, then this value will be falsy.\n * - If a selection is active, but no data points are selected, then this\n * value will be an empty array.\n * - If a selection is active, and data points are selected, then the keys\n * of the selected data points will be present in the array.\n */\n get value() {\n return this._var ? this._var.get() : null;\n }\n\n /**\n * Combines the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n // Important incidental effect: shallow clone is returned\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {string[]} selectedKeys - Falsy, empty array, or array of keys (see\n * {@link SelectionHandle#value}).\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `SelectionHandle` constructor).\n */\n set(selectedKeys, extraInfo) {\n if (this._var)\n this._var.set(selectedKeys, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any that were passed\n * into the `SelectionHandle` constructor).\n */\n clear(extraInfo) {\n if (this._var)\n this.set(void 0, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Subscribes to events on this `SelectionHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {SelectionHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link SelectionHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancels event subscriptions created by {@link SelectionHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|SelectionHandle~listener} listener - Either the callback\n * function previously passed into {@link SelectionHandle#on}, or the\n * string that was returned from {@link SelectionHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n /**\n * Shuts down the `SelectionHandle` object.\n *\n * Removes all event listeners that were added through this handle.\n */\n close() {\n this._emitter.removeAllListeners();\n this.setGroup(null);\n }\n}\n\n/**\n * @callback SelectionHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the selection, or `undefined` if no selection is active),\n * `oldValue` (the previous value of the selection), and `sender` (the\n * `SelectionHandle` instance that made the change).\n */\n\n/**\n * @event SelectionHandle#change\n * @type {object}\n * @property {object} value - The new value of the selection, or `undefined`\n * if no selection is active.\n * @property {object} oldValue - The previous value of the selection.\n * @property {SelectionHandle} sender - The `SelectionHandle` instance that\n * changed the value.\n */\n","export function extend(target, ...sources) {\n for (let i = 0; i < sources.length; i++) {\n let src = sources[i];\n if (typeof(src) === \"undefined\" || src === null)\n continue;\n\n for (let key in src) {\n if (src.hasOwnProperty(key)) {\n target[key] = src[key];\n }\n }\n }\n return target;\n}\n\nexport function checkSorted(list) {\n for (let i = 1; i < list.length; i++) {\n if (list[i] <= list[i-1]) {\n throw new Error(\"List is not sorted or contains duplicate\");\n }\n }\n}\n\nexport function diffSortedLists(a, b) {\n let i_a = 0;\n let i_b = 0;\n\n if (!a) a = [];\n if (!b) b = [];\n\n let a_only = [];\n let b_only = [];\n\n checkSorted(a);\n checkSorted(b);\n\n while (i_a < a.length && i_b < b.length) {\n if (a[i_a] === b[i_b]) {\n i_a++;\n i_b++;\n } else if (a[i_a] < b[i_b]) {\n a_only.push(a[i_a++]);\n } else {\n b_only.push(b[i_b++]);\n }\n }\n\n if (i_a < a.length)\n a_only = a_only.concat(a.slice(i_a));\n if (i_b < b.length)\n b_only = b_only.concat(b.slice(i_b));\n return {\n removed: a_only,\n added: b_only\n };\n}\n\n// Convert from wide: { colA: [1,2,3], colB: [4,5,6], ... }\n// to long: [ {colA: 1, colB: 4}, {colA: 2, colB: 5}, ... ]\nexport function dataframeToD3(df) {\n let names = [];\n let length;\n for (let name in df) {\n if (df.hasOwnProperty(name))\n names.push(name);\n if (typeof(df[name]) !== \"object\" || typeof(df[name].length) === \"undefined\") {\n throw new Error(\"All fields must be arrays\");\n } else if (typeof(length) !== \"undefined\" && length !== df[name].length) {\n throw new Error(\"All fields must be arrays of the same length\");\n }\n length = df[name].length;\n }\n let results = [];\n let item;\n for (let row = 0; row < length; row++) {\n item = {};\n for (let col = 0; col < names.length; col++) {\n item[names[col]] = df[names[col]][row];\n }\n results.push(item);\n }\n return results;\n}\n\n/**\n * Keeps track of all event listener additions/removals and lets all active\n * listeners be removed with a single operation.\n *\n * @private\n */\nexport class SubscriptionTracker {\n constructor(emitter) {\n this._emitter = emitter;\n this._subs = {};\n }\n\n on(eventType, listener) {\n let sub = this._emitter.on(eventType, listener);\n this._subs[sub] = eventType;\n return sub;\n }\n\n off(eventType, listener) {\n let sub = this._emitter.off(eventType, listener);\n if (sub) {\n delete this._subs[sub];\n }\n return sub;\n }\n\n removeAllListeners() {\n let current_subs = this._subs;\n this._subs = {};\n Object.keys(current_subs).forEach((sub) => {\n this._emitter.off(current_subs[sub], sub);\n });\n }\n}\n","import Events from \"./events\";\n\nexport default class Var {\n constructor(group, name, /*optional*/ value) {\n this._group = group;\n this._name = name;\n this._value = value;\n this._events = new Events();\n }\n\n get() {\n return this._value;\n }\n\n set(value, /*optional*/ event) {\n if (this._value === value) {\n // Do nothing; the value hasn't changed\n return;\n }\n let oldValue = this._value;\n this._value = value;\n // Alert JavaScript listeners that the value has changed\n let evt = {};\n if (event && typeof(event) === \"object\") {\n for (let k in event) {\n if (event.hasOwnProperty(k))\n evt[k] = event[k];\n }\n }\n evt.oldValue = oldValue;\n evt.value = value;\n this._events.trigger(\"change\", evt, this);\n\n // TODO: Make this extensible, to let arbitrary back-ends know that\n // something has changed\n if (global.Shiny && global.Shiny.onInputChange) {\n global.Shiny.onInputChange(\n \".clientValue-\" +\n (this._group.name !== null ? this._group.name + \"-\" : \"\") +\n this._name,\n typeof(value) === \"undefined\" ? null : value\n );\n }\n }\n\n on(eventType, listener) {\n return this._events.on(eventType, listener);\n }\n\n off(eventType, listener) {\n return this._events.off(eventType, listener);\n }\n}\n"]} \ No newline at end of file diff --git a/docs/site_libs/crosstalk-1.2.1/scss/crosstalk.scss b/docs/site_libs/crosstalk-1.2.1/scss/crosstalk.scss new file mode 100644 index 000000000..35665616f --- /dev/null +++ b/docs/site_libs/crosstalk-1.2.1/scss/crosstalk.scss @@ -0,0 +1,75 @@ +/* Adjust margins outwards, so column contents line up with the edges of the + parent of container-fluid. */ +.container-fluid.crosstalk-bscols { + margin-left: -30px; + margin-right: -30px; + white-space: normal; +} + +/* But don't adjust the margins outwards if we're directly under the body, + i.e. we were the top-level of something at the console. */ +body > .container-fluid.crosstalk-bscols { + margin-left: auto; + margin-right: auto; +} + +.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { + display: inline-block; + padding-right: 12px; + vertical-align: top; +} + +@media only screen and (max-width:480px) { + .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { + display: block; + padding-right: inherit; + } +} + +/* Relevant BS3 styles to make filter_checkbox() look reasonable without Bootstrap */ +.crosstalk-input { + margin-bottom: 15px; /* a la .form-group */ + .control-label { + margin-bottom: 0; + vertical-align: middle; + } + input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px; + line-height: normal; + } + .checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; + } + .checkbox > label{ + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + cursor: pointer; + } + .checkbox input[type="checkbox"], + .checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 2px; + margin-left: -20px; + } + .checkbox + .checkbox { + margin-top: -5px; + } + .checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + vertical-align: middle; + cursor: pointer; + } + .checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; + } +} diff --git a/docs/site_libs/datatables-binding-0.33/datatables.js b/docs/site_libs/datatables-binding-0.33/datatables.js new file mode 100644 index 000000000..765b53cb1 --- /dev/null +++ b/docs/site_libs/datatables-binding-0.33/datatables.js @@ -0,0 +1,1539 @@ +(function() { + +// some helper functions: using a global object DTWidget so that it can be used +// in JS() code, e.g. datatable(options = list(foo = JS('code'))); unlike R's +// dynamic scoping, when 'code' is eval'ed, JavaScript does not know objects +// from the "parent frame", e.g. JS('DTWidget') will not work unless it was made +// a global object +var DTWidget = {}; + +// 123456666.7890 -> 123,456,666.7890 +var markInterval = function(d, digits, interval, mark, decMark, precision) { + x = precision ? d.toPrecision(digits) : d.toFixed(digits); + if (!/^-?[\d.]+$/.test(x)) return x; + var xv = x.split('.'); + if (xv.length > 2) return x; // should have at most one decimal point + xv[0] = xv[0].replace(new RegExp('\\B(?=(\\d{' + interval + '})+(?!\\d))', 'g'), mark); + return xv.join(decMark); +}; + +DTWidget.formatCurrency = function(data, currency, digits, interval, mark, decMark, before, zeroPrint) { + var d = parseFloat(data); + if (isNaN(d)) return ''; + if (zeroPrint !== null && d === 0.0) return zeroPrint; + var res = markInterval(d, digits, interval, mark, decMark); + res = before ? (/^-/.test(res) ? '-' + currency + res.replace(/^-/, '') : currency + res) : + res + currency; + return res; +}; + +DTWidget.formatString = function(data, prefix, suffix) { + var d = data; + if (d === null) return ''; + return prefix + d + suffix; +}; + +DTWidget.formatPercentage = function(data, digits, interval, mark, decMark, zeroPrint) { + var d = parseFloat(data); + if (isNaN(d)) return ''; + if (zeroPrint !== null && d === 0.0) return zeroPrint; + return markInterval(d * 100, digits, interval, mark, decMark) + '%'; +}; + +DTWidget.formatRound = function(data, digits, interval, mark, decMark, zeroPrint) { + var d = parseFloat(data); + if (isNaN(d)) return ''; + if (zeroPrint !== null && d === 0.0) return zeroPrint; + return markInterval(d, digits, interval, mark, decMark); +}; + +DTWidget.formatSignif = function(data, digits, interval, mark, decMark, zeroPrint) { + var d = parseFloat(data); + if (isNaN(d)) return ''; + if (zeroPrint !== null && d === 0.0) return zeroPrint; + return markInterval(d, digits, interval, mark, decMark, true); +}; + +DTWidget.formatDate = function(data, method, params) { + var d = data; + if (d === null) return ''; + // (new Date('2015-10-28')).toDateString() may return 2015-10-27 because the + // actual time created could be like 'Tue Oct 27 2015 19:00:00 GMT-0500 (CDT)', + // i.e. the date-only string is treated as UTC time instead of local time + if ((method === 'toDateString' || method === 'toLocaleDateString') && /^\d{4,}\D\d{2}\D\d{2}$/.test(d)) { + d = d.split(/\D/); + d = new Date(d[0], d[1] - 1, d[2]); + } else { + d = new Date(d); + } + return d[method].apply(d, params); +}; + +window.DTWidget = DTWidget; + +// A helper function to update the properties of existing filters +var setFilterProps = function(td, props) { + // Update enabled/disabled state + var $input = $(td).find('input').first(); + var searchable = $input.data('searchable'); + $input.prop('disabled', !searchable || props.disabled); + + // Based on the filter type, set its new values + var type = td.getAttribute('data-type'); + if (['factor', 'logical'].includes(type)) { + // Reformat the new dropdown options for use with selectize + var new_vals = props.params.options.map(function(item) { + return { text: item, value: item }; + }); + + // Find the selectize object + var dropdown = $(td).find('.selectized').eq(0)[0].selectize; + + // Note the current values + var old_vals = dropdown.getValue(); + + // Remove the existing values + dropdown.clearOptions(); + + // Add the new options + dropdown.addOption(new_vals); + + // Preserve the existing values + dropdown.setValue(old_vals); + + } else if (['number', 'integer', 'date', 'time'].includes(type)) { + // Apply internal scaling to new limits. Updating scale not yet implemented. + var slider = $(td).find('.noUi-target').eq(0); + var scale = Math.pow(10, Math.max(0, +slider.data('scale') || 0)); + var new_vals = [props.params.min * scale, props.params.max * scale]; + + // Note what the new limits will be just for this filter + var new_lims = new_vals.slice(); + + // Determine the current values and limits + var old_vals = slider.val().map(Number); + var old_lims = slider.noUiSlider('options').range; + old_lims = [old_lims.min, old_lims.max]; + + // Preserve the current values if filters have been applied; otherwise, apply no filtering + if (old_vals[0] != old_lims[0]) { + new_vals[0] = Math.max(old_vals[0], new_vals[0]); + } + + if (old_vals[1] != old_lims[1]) { + new_vals[1] = Math.min(old_vals[1], new_vals[1]); + } + + // Update the endpoints of the slider + slider.noUiSlider({ + start: new_vals, + range: {'min': new_lims[0], 'max': new_lims[1]} + }, true); + } +}; + +var transposeArray2D = function(a) { + return a.length === 0 ? a : HTMLWidgets.transposeArray2D(a); +}; + +var crosstalkPluginsInstalled = false; + +function maybeInstallCrosstalkPlugins() { + if (crosstalkPluginsInstalled) + return; + crosstalkPluginsInstalled = true; + + $.fn.dataTable.ext.afnFiltering.push( + function(oSettings, aData, iDataIndex) { + var ctfilter = oSettings.nTable.ctfilter; + if (ctfilter && !ctfilter[iDataIndex]) + return false; + + var ctselect = oSettings.nTable.ctselect; + if (ctselect && !ctselect[iDataIndex]) + return false; + + return true; + } + ); +} + +HTMLWidgets.widget({ + name: "datatables", + type: "output", + renderOnNullValue: true, + initialize: function(el, width, height) { + // in order that the type=number inputs return a number + $.valHooks.number = { + get: function(el) { + var value = parseFloat(el.value); + return isNaN(value) ? "" : value; + } + }; + $(el).html(' '); + return { + data: null, + ctfilterHandle: new crosstalk.FilterHandle(), + ctfilterSubscription: null, + ctselectHandle: new crosstalk.SelectionHandle(), + ctselectSubscription: null + }; + }, + renderValue: function(el, data, instance) { + if (el.offsetWidth === 0 || el.offsetHeight === 0) { + instance.data = data; + return; + } + instance.data = null; + var $el = $(el); + $el.empty(); + + if (data === null) { + $el.append(' '); + // clear previous Shiny inputs (if any) + for (var i in instance.clearInputs) instance.clearInputs[i](); + instance.clearInputs = {}; + return; + } + + var crosstalkOptions = data.crosstalkOptions; + if (!crosstalkOptions) crosstalkOptions = { + 'key': null, 'group': null + }; + if (crosstalkOptions.group) { + maybeInstallCrosstalkPlugins(); + instance.ctfilterHandle.setGroup(crosstalkOptions.group); + instance.ctselectHandle.setGroup(crosstalkOptions.group); + } + + // if we are in the viewer then we always want to fillContainer and + // and autoHideNavigation (unless the user has explicitly set these) + if (window.HTMLWidgets.viewerMode) { + if (!data.hasOwnProperty("fillContainer")) + data.fillContainer = true; + if (!data.hasOwnProperty("autoHideNavigation")) + data.autoHideNavigation = true; + } + + // propagate fillContainer to instance (so we have it in resize) + instance.fillContainer = data.fillContainer; + + var cells = data.data; + + if (cells instanceof Array) cells = transposeArray2D(cells); + + $el.append(data.container); + var $table = $el.find('table'); + if (data.class) $table.addClass(data.class); + if (data.caption) $table.prepend(data.caption); + + if (!data.selection) data.selection = { + mode: 'none', selected: null, target: 'row', selectable: null + }; + if (HTMLWidgets.shinyMode && data.selection.mode !== 'none' && + data.selection.target === 'row+column') { + if ($table.children('tfoot').length === 0) { + $table.append($('')); + $table.find('thead tr').clone().appendTo($table.find('tfoot')); + } + } + + // column filters + var filterRow; + switch (data.filter) { + case 'top': + $table.children('thead').append(data.filterHTML); + filterRow = $table.find('thead tr:last td'); + break; + case 'bottom': + if ($table.children('tfoot').length === 0) { + $table.append($('')); + } + $table.children('tfoot').prepend(data.filterHTML); + filterRow = $table.find('tfoot tr:first td'); + break; + } + + var options = { searchDelay: 1000 }; + if (cells !== null) $.extend(options, { + data: cells + }); + + // options for fillContainer + var bootstrapActive = typeof($.fn.popover) != 'undefined'; + if (instance.fillContainer) { + + // force scrollX/scrollY and turn off autoWidth + options.scrollX = true; + options.scrollY = "100px"; // can be any value, we'll adjust below + + // if we aren't paginating then move around the info/filter controls + // to save space at the bottom and rephrase the info callback + if (data.options.paging === false) { + + // we know how to do this cleanly for bootstrap, not so much + // for other themes/layouts + if (bootstrapActive) { + options.dom = "<'row'<'col-sm-4'i><'col-sm-8'f>>" + + "<'row'<'col-sm-12'tr>>"; + } + + options.fnInfoCallback = function(oSettings, iStart, iEnd, + iMax, iTotal, sPre) { + return Number(iTotal).toLocaleString() + " records"; + }; + } + } + + // auto hide navigation if requested + // Note, this only works on client-side processing mode as on server-side, + // cells (data.data) is null; In addition, we require the pageLength option + // being provided explicitly to enable this. Despite we may be able to deduce + // the default value of pageLength, it may complicate things so we'd rather + // put this responsiblity to users and warn them on the R side. + if (data.autoHideNavigation === true && data.options.paging !== false) { + // strip all nav if length >= cells + if ((cells instanceof Array) && data.options.pageLength >= cells.length) + options.dom = bootstrapActive ? "<'row'<'col-sm-12'tr>>" : "t"; + // alternatively lean things out for flexdashboard mobile portrait + else if (bootstrapActive && window.FlexDashboard && window.FlexDashboard.isMobilePhone()) + options.dom = "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-12'tr>>" + + "<'row'<'col-sm-12'p>>"; + } + + $.extend(true, options, data.options || {}); + + var searchCols = options.searchCols; + if (searchCols) { + searchCols = searchCols.map(function(x) { + return x === null ? '' : x.search; + }); + // FIXME: this means I don't respect the escapeRegex setting + delete options.searchCols; + } + + // server-side processing? + var server = options.serverSide === true; + + // use the dataSrc function to pre-process JSON data returned from R + var DT_rows_all = [], DT_rows_current = []; + if (server && HTMLWidgets.shinyMode && typeof options.ajax === 'object' && + /^session\/[\da-z]+\/dataobj/.test(options.ajax.url) && !options.ajax.dataSrc) { + options.ajax.dataSrc = function(json) { + DT_rows_all = $.makeArray(json.DT_rows_all); + DT_rows_current = $.makeArray(json.DT_rows_current); + var data = json.data; + if (!colReorderEnabled()) return data; + var table = $table.DataTable(), order = table.colReorder.order(), flag = true, i, j, row; + for (i = 0; i < order.length; ++i) if (order[i] !== i) flag = false; + if (flag) return data; + for (i = 0; i < data.length; ++i) { + row = data[i].slice(); + for (j = 0; j < order.length; ++j) data[i][j] = row[order[j]]; + } + return data; + }; + } + + var thiz = this; + if (instance.fillContainer) $table.on('init.dt', function(e) { + thiz.fillAvailableHeight(el, $(el).innerHeight()); + }); + // If the page contains serveral datatables and one of which enables colReorder, + // the table.colReorder.order() function will exist but throws error when called. + // So it seems like the only way to know if colReorder is enabled or not is to + // check the options. + var colReorderEnabled = function() { return "colReorder" in options; }; + var table = $table.DataTable(options); + $el.data('datatable', table); + + if ('rowGroup' in options) { + // Maintain RowGroup dataSrc when columns are reordered (#1109) + table.on('column-reorder', function(e, settings, details) { + var oldDataSrc = table.rowGroup().dataSrc(); + var newDataSrc = details.mapping[oldDataSrc]; + table.rowGroup().dataSrc(newDataSrc); + }); + } + + // Unregister previous Crosstalk event subscriptions, if they exist + if (instance.ctfilterSubscription) { + instance.ctfilterHandle.off("change", instance.ctfilterSubscription); + instance.ctfilterSubscription = null; + } + if (instance.ctselectSubscription) { + instance.ctselectHandle.off("change", instance.ctselectSubscription); + instance.ctselectSubscription = null; + } + + if (!crosstalkOptions.group) { + $table[0].ctfilter = null; + $table[0].ctselect = null; + } else { + var key = crosstalkOptions.key; + function keysToMatches(keys) { + if (!keys) { + return null; + } else { + var selectedKeys = {}; + for (var i = 0; i < keys.length; i++) { + selectedKeys[keys[i]] = true; + } + var matches = {}; + for (var j = 0; j < key.length; j++) { + if (selectedKeys[key[j]]) + matches[j] = true; + } + return matches; + } + } + + function applyCrosstalkFilter(e) { + $table[0].ctfilter = keysToMatches(e.value); + table.draw(); + } + instance.ctfilterSubscription = instance.ctfilterHandle.on("change", applyCrosstalkFilter); + applyCrosstalkFilter({value: instance.ctfilterHandle.filteredKeys}); + + function applyCrosstalkSelection(e) { + if (e.sender !== instance.ctselectHandle) { + table + .rows('.' + selClass, {search: 'applied'}) + .nodes() + .to$() + .removeClass(selClass); + if (selectedRows) + changeInput('rows_selected', selectedRows(), void 0, true); + } + + if (e.sender !== instance.ctselectHandle && e.value && e.value.length) { + var matches = keysToMatches(e.value); + + // persistent selection with plotly (& leaflet) + var ctOpts = crosstalk.var("plotlyCrosstalkOpts").get() || {}; + if (ctOpts.persistent === true) { + var matches = $.extend(matches, $table[0].ctselect); + } + + $table[0].ctselect = matches; + table.draw(); + } else { + if ($table[0].ctselect) { + $table[0].ctselect = null; + table.draw(); + } + } + } + instance.ctselectSubscription = instance.ctselectHandle.on("change", applyCrosstalkSelection); + // TODO: This next line doesn't seem to work when renderDataTable is used + applyCrosstalkSelection({value: instance.ctselectHandle.value}); + } + + var inArray = function(val, array) { + return $.inArray(val, $.makeArray(array)) > -1; + }; + + // search the i-th column + var searchColumn = function(i, value) { + var regex = false, ci = true; + if (options.search) { + regex = options.search.regex, + ci = options.search.caseInsensitive !== false; + } + // need to transpose the column index when colReorder is enabled + if (table.colReorder) i = table.colReorder.transpose(i); + return table.column(i).search(value, regex, !regex, ci); + }; + + if (data.filter !== 'none') { + if (!data.hasOwnProperty('filterSettings')) data.filterSettings = {}; + + filterRow.each(function(i, td) { + + var $td = $(td), type = $td.data('type'), filter; + var $input = $td.children('div').first().children('input'); + var disabled = $input.prop('disabled'); + var searchable = table.settings()[0].aoColumns[i].bSearchable; + $input.prop('disabled', !searchable || disabled); + $input.data('searchable', searchable); // for updating later + $input.on('input blur', function() { + $input.next('span').toggle(Boolean($input.val())); + }); + // Bootstrap sets pointer-events to none and we won't be able to click + // the clear button + $input.next('span').css('pointer-events', 'auto').hide().click(function() { + $(this).hide().prev('input').val('').trigger('input').focus(); + }); + var searchCol; // search string for this column + if (searchCols && searchCols[i]) { + searchCol = searchCols[i]; + $input.val(searchCol).trigger('input'); + } + var $x = $td.children('div').last(); + + // remove the overflow: hidden attribute of the scrollHead + // (otherwise the scrolling table body obscures the filters) + // The workaround and the discussion from + // https://github.com/rstudio/DT/issues/554#issuecomment-518007347 + // Otherwise the filter selection will not be anchored to the values + // when the columns number is many and scrollX is enabled. + var scrollHead = $(el).find('.dataTables_scrollHead,.dataTables_scrollFoot'); + var cssOverflowHead = scrollHead.css('overflow'); + var scrollBody = $(el).find('.dataTables_scrollBody'); + var cssOverflowBody = scrollBody.css('overflow'); + var scrollTable = $(el).find('.dataTables_scroll'); + var cssOverflowTable = scrollTable.css('overflow'); + if (cssOverflowHead === 'hidden') { + $x.on('show hide', function(e) { + if (e.type === 'show') { + scrollHead.css('overflow', 'visible'); + scrollBody.css('overflow', 'visible'); + scrollTable.css('overflow-x', 'scroll'); + } else { + scrollHead.css('overflow', cssOverflowHead); + scrollBody.css('overflow', cssOverflowBody); + scrollTable.css('overflow-x', cssOverflowTable); + } + }); + $x.css('z-index', 25); + } + + if (inArray(type, ['factor', 'logical'])) { + $input.on({ + click: function() { + $input.parent().hide(); $x.show().trigger('show'); filter[0].selectize.focus(); + }, + input: function() { + var v1 = JSON.stringify(filter[0].selectize.getValue()), v2 = $input.val(); + if (v1 === '[]') v1 = ''; + if (v1 !== v2) filter[0].selectize.setValue(v2 === '' ? [] : JSON.parse(v2)); + } + }); + var $input2 = $x.children('select'); + filter = $input2.selectize($.extend({ + options: $input2.data('options').map(function(v, i) { + return ({text: v, value: v}); + }), + plugins: ['remove_button'], + hideSelected: true, + onChange: function(value) { + if (value === null) value = []; // compatibility with jQuery 3.0 + $input.val(value.length ? JSON.stringify(value) : ''); + if (value.length) $input.trigger('input'); + $input.attr('title', $input.val()); + if (server) { + searchColumn(i, value.length ? JSON.stringify(value) : '').draw(); + return; + } + // turn off filter if nothing selected + $td.data('filter', value.length > 0); + table.draw(); // redraw table, and filters will be applied + } + }, data.filterSettings.select)); + filter[0].selectize.on('blur', function() { + $x.hide().trigger('hide'); $input.parent().show(); $input.trigger('blur'); + }); + filter.next('div').css('margin-bottom', 'auto'); + } else if (type === 'character') { + var fun = function() { + searchColumn(i, $input.val()).draw(); + }; + // throttle searching for server-side processing + var throttledFun = $.fn.dataTable.util.throttle(fun, options.searchDelay); + $input.on('input', function(e, immediate) { + // always bypass throttling when immediate = true (via the updateSearch method) + (immediate || !server) ? fun() : throttledFun(); + }); + } else if (inArray(type, ['number', 'integer', 'date', 'time'])) { + var $x0 = $x; + $x = $x0.children('div').first(); + $x0.css({ + 'background-color': '#fff', + 'border': '1px #ddd solid', + 'border-radius': '4px', + 'padding': data.vertical ? '35px 20px': '20px 20px 10px 20px' + }); + var $spans = $x0.children('span').css({ + 'margin-top': data.vertical ? '0' : '10px', + 'white-space': 'nowrap' + }); + var $span1 = $spans.first(), $span2 = $spans.last(); + var r1 = +$x.data('min'), r2 = +$x.data('max'); + // when the numbers are too small or have many decimal places, the + // slider may have numeric precision problems (#150) + var scale = Math.pow(10, Math.max(0, +$x.data('scale') || 0)); + r1 = Math.round(r1 * scale); r2 = Math.round(r2 * scale); + var scaleBack = function(x, scale) { + if (scale === 1) return x; + var d = Math.round(Math.log(scale) / Math.log(10)); + // to avoid problems like 3.423/100 -> 0.034230000000000003 + return (x / scale).toFixed(d); + }; + var slider_min = function() { + return filter.noUiSlider('options').range.min; + }; + var slider_max = function() { + return filter.noUiSlider('options').range.max; + }; + $input.on({ + focus: function() { + $x0.show().trigger('show'); + // first, make sure the slider div leaves at least 20px between + // the two (slider value) span's + $x0.width(Math.max(160, $span1.outerWidth() + $span2.outerWidth() + 20)); + // then, if the input is really wide or slider is vertical, + // make the slider the same width as the input + if ($x0.outerWidth() < $input.outerWidth() || data.vertical) { + $x0.outerWidth($input.outerWidth()); + } + // make sure the slider div does not reach beyond the right margin + if ($(window).width() < $x0.offset().left + $x0.width()) { + $x0.offset({ + 'left': $input.offset().left + $input.outerWidth() - $x0.outerWidth() + }); + } + }, + blur: function() { + $x0.hide().trigger('hide'); + }, + input: function() { + if ($input.val() === '') filter.val([slider_min(), slider_max()]); + }, + change: function() { + var v = $input.val().replace(/\s/g, ''); + if (v === '') return; + v = v.split('...'); + if (v.length !== 2) { + $input.parent().addClass('has-error'); + return; + } + if (v[0] === '') v[0] = slider_min(); + if (v[1] === '') v[1] = slider_max(); + $input.parent().removeClass('has-error'); + // treat date as UTC time at midnight + var strTime = function(x) { + var s = type === 'date' ? 'T00:00:00Z' : ''; + var t = new Date(x + s).getTime(); + // add 10 minutes to date since it does not hurt the date, and + // it helps avoid the tricky floating point arithmetic problems, + // e.g. sometimes the date may be a few milliseconds earlier + // than the midnight due to precision problems in noUiSlider + return type === 'date' ? t + 3600000 : t; + }; + if (inArray(type, ['date', 'time'])) { + v[0] = strTime(v[0]); + v[1] = strTime(v[1]); + } + if (v[0] != slider_min()) v[0] *= scale; + if (v[1] != slider_max()) v[1] *= scale; + filter.val(v); + } + }); + var formatDate = function(d) { + d = scaleBack(d, scale); + if (type === 'number') return d; + if (type === 'integer') return parseInt(d); + var x = new Date(+d); + if (type === 'date') { + var pad0 = function(x) { + return ('0' + x).substr(-2, 2); + }; + return x.getUTCFullYear() + '-' + pad0(1 + x.getUTCMonth()) + + '-' + pad0(x.getUTCDate()); + } else { + return x.toISOString(); + } + }; + var opts = type === 'date' ? { step: 60 * 60 * 1000 } : + type === 'integer' ? { step: 1 } : {}; + + opts.orientation = data.vertical ? 'vertical': 'horizontal'; + opts.direction = data.vertical ? 'rtl': 'ltr'; + + filter = $x.noUiSlider($.extend({ + start: [r1, r2], + range: {min: r1, max: r2}, + connect: true + }, opts, data.filterSettings.slider)); + if (scale > 1) (function() { + var t1 = r1, t2 = r2; + var val = filter.val(); + while (val[0] > r1 || val[1] < r2) { + if (val[0] > r1) { + t1 -= val[0] - r1; + } + if (val[1] < r2) { + t2 += r2 - val[1]; + } + filter = $x.noUiSlider($.extend({ + start: [t1, t2], + range: {min: t1, max: t2}, + connect: true + }, opts, data.filterSettings.slider), true); + val = filter.val(); + } + r1 = t1; r2 = t2; + })(); + // format with active column renderer, if defined + var colDef = data.options.columnDefs.find(function(def) { + return (def.targets === i || inArray(i, def.targets)) && 'render' in def; + }); + var updateSliderText = function(v1, v2) { + // we only know how to use function renderers + if (colDef && typeof colDef.render === 'function') { + var restore = function(v) { + v = scaleBack(v, scale); + return inArray(type, ['date', 'time']) ? new Date(+v) : v; + } + $span1.text(colDef.render(restore(v1), 'display')); + $span2.text(colDef.render(restore(v2), 'display')); + } else { + $span1.text(formatDate(v1)); + $span2.text(formatDate(v2)); + } + }; + updateSliderText(r1, r2); + var updateSlider = function(e) { + var val = filter.val(); + // turn off filter if in full range + $td.data('filter', val[0] > slider_min() || val[1] < slider_max()); + var v1 = formatDate(val[0]), v2 = formatDate(val[1]), ival; + if ($td.data('filter')) { + ival = v1 + ' ... ' + v2; + $input.attr('title', ival).val(ival).trigger('input'); + } else { + $input.attr('title', '').val(''); + } + updateSliderText(val[0], val[1]); + if (e.type === 'slide') return; // no searching when sliding only + if (server) { + searchColumn(i, $td.data('filter') ? ival : '').draw(); + return; + } + table.draw(); + }; + filter.on({ + set: updateSlider, + slide: updateSlider + }); + } + + // server-side processing will be handled by R (or whatever server + // language you use); the following code is only needed for client-side + // processing + if (server) { + // if a search string has been pre-set, search now + if (searchCol) $input.trigger('input').trigger('change'); + return; + } + + var customFilter = function(settings, data, dataIndex) { + // there is no way to attach a search function to a specific table, + // and we need to make sure a global search function is not applied to + // all tables (i.e. a range filter in a previous table should not be + // applied to the current table); we use the settings object to + // determine if we want to perform searching on the current table, + // since settings.sTableId will be different to different tables + if (table.settings()[0] !== settings) return true; + // no filter on this column or no need to filter this column + if (typeof filter === 'undefined' || !$td.data('filter')) return true; + + var r = filter.val(), v, r0, r1; + var i_data = function(i) { + if (!colReorderEnabled()) return i; + var order = table.colReorder.order(), k; + for (k = 0; k < order.length; ++k) if (order[k] === i) return k; + return i; // in theory it will never be here... + } + v = data[i_data(i)]; + if (type === 'number' || type === 'integer') { + v = parseFloat(v); + // how to handle NaN? currently exclude these rows + if (isNaN(v)) return(false); + r0 = parseFloat(scaleBack(r[0], scale)) + r1 = parseFloat(scaleBack(r[1], scale)); + if (v >= r0 && v <= r1) return true; + } else if (type === 'date' || type === 'time') { + v = new Date(v); + r0 = new Date(r[0] / scale); r1 = new Date(r[1] / scale); + if (v >= r0 && v <= r1) return true; + } else if (type === 'factor') { + if (r.length === 0 || inArray(v, r)) return true; + } else if (type === 'logical') { + if (r.length === 0) return true; + if (inArray(v === '' ? 'na' : v, r)) return true; + } + return false; + }; + + $.fn.dataTable.ext.search.push(customFilter); + + // search for the preset search strings if it is non-empty + if (searchCol) $input.trigger('input').trigger('change'); + + }); + + } + + // highlight search keywords + var highlight = function() { + var body = $(table.table().body()); + // removing the old highlighting first + body.unhighlight(); + + // don't highlight the "not found" row, so we get the rows using the api + if (table.rows({ filter: 'applied' }).data().length === 0) return; + // highlight global search keywords + body.highlight($.trim(table.search()).split(/\s+/)); + // then highlight keywords from individual column filters + if (filterRow) filterRow.each(function(i, td) { + var $td = $(td), type = $td.data('type'); + if (type !== 'character') return; + var $input = $td.children('div').first().children('input'); + var column = table.column(i).nodes().to$(), + val = $.trim($input.val()); + if (type !== 'character' || val === '') return; + column.highlight(val.split(/\s+/)); + }); + }; + + if (options.searchHighlight) { + table + .on('draw.dt.dth column-visibility.dt.dth column-reorder.dt.dth', highlight) + .on('destroy', function() { + // remove event handler + table.off('draw.dt.dth column-visibility.dt.dth column-reorder.dt.dth'); + }); + + // Set the option for escaping regex characters in our search string. This will be used + // for all future matching. + jQuery.fn.highlight.options.escapeRegex = (!options.search || !options.search.regex); + + // initial highlight for state saved conditions and initial states + highlight(); + } + + // run the callback function on the table instance + if (typeof data.callback === 'function') data.callback(table); + + // double click to edit the cell, row, column, or all cells + if (data.editable) table.on('dblclick.dt', 'tbody td', function(e) { + // only bring up the editor when the cell itself is dbclicked, and ignore + // other dbclick events bubbled up (e.g. from the ) + if (e.target !== this) return; + var target = [], immediate = false; + switch (data.editable.target) { + case 'cell': + target = [this]; + immediate = true; // edit will take effect immediately + break; + case 'row': + target = table.cells(table.cell(this).index().row, '*').nodes(); + break; + case 'column': + target = table.cells('*', table.cell(this).index().column).nodes(); + break; + case 'all': + target = table.cells().nodes(); + break; + default: + throw 'The editable parameter must be "cell", "row", "column", or "all"'; + } + var disableCols = data.editable.disable ? data.editable.disable.columns : null; + var numericCols = data.editable.numeric; + var areaCols = data.editable.area; + var dateCols = data.editable.date; + for (var i = 0; i < target.length; i++) { + (function(cell, current) { + var $cell = $(cell), html = $cell.html(); + var _cell = table.cell(cell), value = _cell.data(), index = _cell.index().column; + var $input; + if (inArray(index, numericCols)) { + $input = $(''); + } else if (inArray(index, areaCols)) { + $input = $(''); + } else if (inArray(index, dateCols)) { + $input = $(''); + } else { + $input = $(''); + } + if (!immediate) { + $cell.data('input', $input).data('html', html); + $input.attr('title', 'Hit Ctrl+Enter to finish editing, or Esc to cancel'); + } + $input.val(value); + if (inArray(index, disableCols)) { + $input.attr('readonly', '').css('filter', 'invert(25%)'); + } + $cell.empty().append($input); + if (cell === current) $input.focus(); + $input.css('width', '100%'); + + if (immediate) $input.on('blur', function(e) { + var valueNew = $input.val(); + if (valueNew !== value) { + _cell.data(valueNew); + if (HTMLWidgets.shinyMode) { + changeInput('cell_edit', [cellInfo(cell)], 'DT.cellInfo', null, {priority: 'event'}); + } + // for server-side processing, users have to call replaceData() to update the table + if (!server) table.draw(false); + } else { + $cell.html(html); + } + }).on('keyup', function(e) { + // hit Escape to cancel editing + if (e.keyCode === 27) $input.trigger('blur'); + }); + + // bulk edit (row, column, or all) + if (!immediate) $input.on('keyup', function(e) { + var removeInput = function($cell, restore) { + $cell.data('input').remove(); + if (restore) $cell.html($cell.data('html')); + } + if (e.keyCode === 27) { + for (var i = 0; i < target.length; i++) { + removeInput($(target[i]), true); + } + } else if (e.keyCode === 13 && e.ctrlKey) { + // Ctrl + Enter + var cell, $cell, _cell, cellData = []; + for (var i = 0; i < target.length; i++) { + cell = target[i]; $cell = $(cell); _cell = table.cell(cell); + _cell.data($cell.data('input').val()); + HTMLWidgets.shinyMode && cellData.push(cellInfo(cell)); + removeInput($cell, false); + } + if (HTMLWidgets.shinyMode) { + changeInput('cell_edit', cellData, 'DT.cellInfo', null, {priority: "event"}); + } + if (!server) table.draw(false); + } + }); + })(target[i], this); + } + }); + + // interaction with shiny + if (!HTMLWidgets.shinyMode && !crosstalkOptions.group) return; + + var methods = {}; + var shinyData = {}; + + methods.updateCaption = function(caption) { + if (!caption) return; + $table.children('caption').replaceWith(caption); + } + + // register clear functions to remove input values when the table is removed + instance.clearInputs = {}; + + var changeInput = function(id, value, type, noCrosstalk, opts) { + var event = id; + id = el.id + '_' + id; + if (type) id = id + ':' + type; + // do not update if the new value is the same as old value + if (event !== 'cell_edit' && !/_clicked$/.test(event) && shinyData.hasOwnProperty(id) && shinyData[id] === JSON.stringify(value)) + return; + shinyData[id] = JSON.stringify(value); + if (HTMLWidgets.shinyMode && Shiny.setInputValue) { + Shiny.setInputValue(id, value, opts); + if (!instance.clearInputs[id]) instance.clearInputs[id] = function() { + Shiny.setInputValue(id, null); + } + } + + // HACK + if (event === "rows_selected" && !noCrosstalk) { + if (crosstalkOptions.group) { + var keys = crosstalkOptions.key; + var selectedKeys = null; + if (value) { + selectedKeys = []; + for (var i = 0; i < value.length; i++) { + // The value array's contents use 1-based row numbers, so we must + // convert to 0-based before indexing into the keys array. + selectedKeys.push(keys[value[i] - 1]); + } + } + instance.ctselectHandle.set(selectedKeys); + } + } + }; + + var addOne = function(x) { + return x.map(function(i) { return 1 + i; }); + }; + + var unique = function(x) { + var ux = []; + $.each(x, function(i, el){ + if ($.inArray(el, ux) === -1) ux.push(el); + }); + return ux; + } + + // change the row index of a cell + var tweakCellIndex = function(cell) { + var info = cell.index(); + // some cell may not be valid. e.g, #759 + // when using the RowGroup extension, datatables will + // generate the row label and the cells are not part of + // the data thus contain no row/col info + if (info === undefined) + return {row: null, col: null}; + if (server) { + info.row = DT_rows_current[info.row]; + } else { + info.row += 1; + } + return {row: info.row, col: info.column}; + } + + var cleanSelectedValues = function() { + changeInput('rows_selected', []); + changeInput('columns_selected', []); + changeInput('cells_selected', transposeArray2D([]), 'shiny.matrix'); + } + // #828 we should clean the selection on the server-side when the table reloads + cleanSelectedValues(); + + // a flag to indicates if select extension is initialized or not + var flagSelectExt = table.settings()[0]._select !== undefined; + // the Select extension should only be used in the client mode and + // when the selection.mode is set to none + if (data.selection.mode === 'none' && !server && flagSelectExt) { + var updateRowsSelected = function() { + var rows = table.rows({selected: true}); + var selected = []; + $.each(rows.indexes().toArray(), function(i, v) { + selected.push(v + 1); + }); + changeInput('rows_selected', selected); + } + var updateColsSelected = function() { + var columns = table.columns({selected: true}); + changeInput('columns_selected', columns.indexes().toArray()); + } + var updateCellsSelected = function() { + var cells = table.cells({selected: true}); + var selected = []; + cells.every(function() { + var row = this.index().row; + var col = this.index().column; + selected = selected.concat([[row + 1, col]]); + }); + changeInput('cells_selected', transposeArray2D(selected), 'shiny.matrix'); + } + table.on('select deselect', function(e, dt, type, indexes) { + updateRowsSelected(); + updateColsSelected(); + updateCellsSelected(); + }) + updateRowsSelected(); + updateColsSelected(); + updateCellsSelected(); + } + + var selMode = data.selection.mode, selTarget = data.selection.target; + var selDisable = data.selection.selectable === false; + if (inArray(selMode, ['single', 'multiple'])) { + var selClass = inArray(data.style, ['bootstrap', 'bootstrap4']) ? 'active' : 'selected'; + // selected1: row indices; selected2: column indices + var initSel = function(x) { + if (x === null || typeof x === 'boolean' || selTarget === 'cell') { + return {rows: [], cols: []}; + } else if (selTarget === 'row') { + return {rows: $.makeArray(x), cols: []}; + } else if (selTarget === 'column') { + return {rows: [], cols: $.makeArray(x)}; + } else if (selTarget === 'row+column') { + return {rows: $.makeArray(x.rows), cols: $.makeArray(x.cols)}; + } + } + var selected = data.selection.selected; + var selected1 = initSel(selected).rows, selected2 = initSel(selected).cols; + // selectable should contain either all positive or all non-positive values, not both + // positive values indicate "selectable" while non-positive values means "nonselectable" + // the assertion is performed on R side. (only column indicides could be zero which indicates + // the row name) + var selectable = data.selection.selectable; + var selectable1 = initSel(selectable).rows, selectable2 = initSel(selectable).cols; + + // After users reorder the rows or filter the table, we cannot use the table index + // directly. Instead, we need this function to find out the rows between the two clicks. + // If user filter the table again between the start click and the end click, the behavior + // would be undefined, but it should not be a problem. + var shiftSelRowsIndex = function(start, end) { + var indexes = server ? DT_rows_all : table.rows({ search: 'applied' }).indexes().toArray(); + start = indexes.indexOf(start); end = indexes.indexOf(end); + // if start is larger than end, we need to swap + if (start > end) { + var tmp = end; end = start; start = tmp; + } + return indexes.slice(start, end + 1); + } + + var serverRowIndex = function(clientRowIndex) { + return server ? DT_rows_current[clientRowIndex] : clientRowIndex + 1; + } + + // row, column, or cell selection + var lastClickedRow; + if (inArray(selTarget, ['row', 'row+column'])) { + // Get the current selected rows. It will also + // update the selected1's value based on the current row selection state + // Note we can't put this function inside selectRows() directly, + // the reason is method.selectRows() will override selected1's value but this + // function will add rows to selected1 (keep the existing selection), which is + // inconsistent with column and cell selection. + var selectedRows = function() { + var rows = table.rows('.' + selClass); + var idx = rows.indexes().toArray(); + if (!server) { + selected1 = addOne(idx); + return selected1; + } + idx = idx.map(function(i) { + return DT_rows_current[i]; + }); + selected1 = selMode === 'multiple' ? unique(selected1.concat(idx)) : idx; + return selected1; + } + // Change selected1's value based on selectable1, then refresh the row state + var onlyKeepSelectableRows = function() { + if (selDisable) { // users can't select; useful when only want backend select + selected1 = []; + return; + } + if (selectable1.length === 0) return; + var nonselectable = selectable1[0] <= 0; + if (nonselectable) { + // should make selectable1 positive + selected1 = $(selected1).not(selectable1.map(function(i) { return -i; })).get(); + } else { + selected1 = $(selected1).filter(selectable1).get(); + } + } + // Change selected1's value based on selectable1, then + // refresh the row selection state according to values in selected1 + var selectRows = function(ignoreSelectable) { + if (!ignoreSelectable) onlyKeepSelectableRows(); + table.$('tr.' + selClass).removeClass(selClass); + if (selected1.length === 0) return; + if (server) { + table.rows({page: 'current'}).every(function() { + if (inArray(DT_rows_current[this.index()], selected1)) { + $(this.node()).addClass(selClass); + } + }); + } else { + var selected0 = selected1.map(function(i) { return i - 1; }); + $(table.rows(selected0).nodes()).addClass(selClass); + } + } + table.on('mousedown.dt', 'tbody tr', function(e) { + var $this = $(this), thisRow = table.row(this); + if (selMode === 'multiple') { + if (e.shiftKey && lastClickedRow !== undefined) { + // select or de-select depends on the last clicked row's status + var flagSel = !$this.hasClass(selClass); + var crtClickedRow = serverRowIndex(thisRow.index()); + if (server) { + var rowsIndex = shiftSelRowsIndex(lastClickedRow, crtClickedRow); + // update current page's selClass + rowsIndex.map(function(i) { + var rowIndex = DT_rows_current.indexOf(i); + if (rowIndex >= 0) { + var row = table.row(rowIndex).nodes().to$(); + var flagRowSel = !row.hasClass(selClass); + if (flagSel === flagRowSel) row.toggleClass(selClass); + } + }); + // update selected1 + if (flagSel) { + selected1 = unique(selected1.concat(rowsIndex)); + } else { + selected1 = selected1.filter(function(index) { + return !inArray(index, rowsIndex); + }); + } + } else { + // js starts from 0 + shiftSelRowsIndex(lastClickedRow - 1, crtClickedRow - 1).map(function(value) { + var row = table.row(value).nodes().to$(); + var flagRowSel = !row.hasClass(selClass); + if (flagSel === flagRowSel) row.toggleClass(selClass); + }); + } + e.preventDefault(); + } else { + $this.toggleClass(selClass); + } + } else { + if ($this.hasClass(selClass)) { + $this.removeClass(selClass); + } else { + table.$('tr.' + selClass).removeClass(selClass); + $this.addClass(selClass); + } + } + if (server && !$this.hasClass(selClass)) { + var id = DT_rows_current[thisRow.index()]; + // remove id from selected1 since its class .selected has been removed + if (inArray(id, selected1)) selected1.splice($.inArray(id, selected1), 1); + } + selectedRows(); // update selected1's value based on selClass + selectRows(false); // only keep the selectable rows + changeInput('rows_selected', selected1); + changeInput('row_last_clicked', serverRowIndex(thisRow.index()), null, null, {priority: 'event'}); + lastClickedRow = serverRowIndex(thisRow.index()); + }); + selectRows(false); // in case users have specified pre-selected rows + // restore selected rows after the table is redrawn (e.g. sort/search/page); + // client-side tables will preserve the selections automatically; for + // server-side tables, we have to *real* row indices are in `selected1` + changeInput('rows_selected', selected1); + if (server) table.on('draw.dt', function(e) { selectRows(false); }); + methods.selectRows = function(selected, ignoreSelectable) { + selected1 = $.makeArray(selected); + selectRows(ignoreSelectable); + changeInput('rows_selected', selected1); + } + } + + if (inArray(selTarget, ['column', 'row+column'])) { + if (selTarget === 'row+column') { + $(table.columns().footer()).css('cursor', 'pointer'); + } + // update selected2's value based on selectable2 + var onlyKeepSelectableCols = function() { + if (selDisable) { // users can't select; useful when only want backend select + selected2 = []; + return; + } + if (selectable2.length === 0) return; + var nonselectable = selectable2[0] <= 0; + if (nonselectable) { + // need to make selectable2 positive + selected2 = $(selected2).not(selectable2.map(function(i) { return -i; })).get(); + } else { + selected2 = $(selected2).filter(selectable2).get(); + } + } + // update selected2 and then + // refresh the col selection state according to values in selected2 + var selectCols = function(ignoreSelectable) { + if (!ignoreSelectable) onlyKeepSelectableCols(); + // if selected2 is not a valide index (e.g., larger than the column number) + // table.columns(selected2) will fail and result in a blank table + // this is different from the table.rows(), where the out-of-range indexes + // doesn't affect at all + selected2 = $(selected2).filter(table.columns().indexes()).get(); + table.columns().nodes().flatten().to$().removeClass(selClass); + if (selected2.length > 0) + table.columns(selected2).nodes().flatten().to$().addClass(selClass); + } + var callback = function() { + var colIdx = selTarget === 'column' ? table.cell(this).index().column : + $.inArray(this, table.columns().footer()), + thisCol = $(table.column(colIdx).nodes()); + if (colIdx === -1) return; + if (thisCol.hasClass(selClass)) { + thisCol.removeClass(selClass); + selected2.splice($.inArray(colIdx, selected2), 1); + } else { + if (selMode === 'single') $(table.cells().nodes()).removeClass(selClass); + thisCol.addClass(selClass); + selected2 = selMode === 'single' ? [colIdx] : unique(selected2.concat([colIdx])); + } + selectCols(false); // update selected2 based on selectable + changeInput('columns_selected', selected2); + } + if (selTarget === 'column') { + $(table.table().body()).on('click.dt', 'td', callback); + } else { + $(table.table().footer()).on('click.dt', 'tr th', callback); + } + selectCols(false); // in case users have specified pre-selected columns + changeInput('columns_selected', selected2); + if (server) table.on('draw.dt', function(e) { selectCols(false); }); + methods.selectColumns = function(selected, ignoreSelectable) { + selected2 = $.makeArray(selected); + selectCols(ignoreSelectable); + changeInput('columns_selected', selected2); + } + } + + if (selTarget === 'cell') { + var selected3 = [], selectable3 = []; + if (selected !== null) selected3 = selected; + if (selectable !== null && typeof selectable !== 'boolean') selectable3 = selectable; + var findIndex = function(ij, sel) { + for (var i = 0; i < sel.length; i++) { + if (ij[0] === sel[i][0] && ij[1] === sel[i][1]) return i; + } + return -1; + } + // Change selected3's value based on selectable3, then refresh the cell state + var onlyKeepSelectableCells = function() { + if (selDisable) { // users can't select; useful when only want backend select + selected3 = []; + return; + } + if (selectable3.length === 0) return; + var nonselectable = selectable3[0][0] <= 0; + var out = []; + if (nonselectable) { + selected3.map(function(ij) { + // should make selectable3 positive + if (findIndex([-ij[0], -ij[1]], selectable3) === -1) { out.push(ij); } + }); + } else { + selected3.map(function(ij) { + if (findIndex(ij, selectable3) > -1) { out.push(ij); } + }); + } + selected3 = out; + } + // Change selected3's value based on selectable3, then + // refresh the cell selection state according to values in selected3 + var selectCells = function(ignoreSelectable) { + if (!ignoreSelectable) onlyKeepSelectableCells(); + table.$('td.' + selClass).removeClass(selClass); + if (selected3.length === 0) return; + if (server) { + table.cells({page: 'current'}).every(function() { + var info = tweakCellIndex(this); + if (findIndex([info.row, info.col], selected3) > -1) + $(this.node()).addClass(selClass); + }); + } else { + selected3.map(function(ij) { + $(table.cell(ij[0] - 1, ij[1]).node()).addClass(selClass); + }); + } + }; + table.on('click.dt', 'tbody td', function() { + var $this = $(this), info = tweakCellIndex(table.cell(this)); + if ($this.hasClass(selClass)) { + $this.removeClass(selClass); + selected3.splice(findIndex([info.row, info.col], selected3), 1); + } else { + if (selMode === 'single') $(table.cells().nodes()).removeClass(selClass); + $this.addClass(selClass); + selected3 = selMode === 'single' ? [[info.row, info.col]] : + unique(selected3.concat([[info.row, info.col]])); + } + selectCells(false); // must call this to update selected3 based on selectable3 + changeInput('cells_selected', transposeArray2D(selected3), 'shiny.matrix'); + }); + selectCells(false); // in case users have specified pre-selected columns + changeInput('cells_selected', transposeArray2D(selected3), 'shiny.matrix'); + + if (server) table.on('draw.dt', function(e) { selectCells(false); }); + methods.selectCells = function(selected, ignoreSelectable) { + selected3 = selected ? selected : []; + selectCells(ignoreSelectable); + changeInput('cells_selected', transposeArray2D(selected3), 'shiny.matrix'); + } + } + } + + // expose some table info to Shiny + var updateTableInfo = function(e, settings) { + // TODO: is anyone interested in the page info? + // changeInput('page_info', table.page.info()); + var updateRowInfo = function(id, modifier) { + var idx; + if (server) { + idx = modifier.page === 'current' ? DT_rows_current : DT_rows_all; + } else { + var rows = table.rows($.extend({ + search: 'applied', + page: 'all' + }, modifier)); + idx = addOne(rows.indexes().toArray()); + } + changeInput('rows' + '_' + id, idx); + }; + updateRowInfo('current', {page: 'current'}); + updateRowInfo('all', {}); + } + table.on('draw.dt', updateTableInfo); + updateTableInfo(); + + // state info + table.on('draw.dt column-visibility.dt', function() { + changeInput('state', table.state()); + }); + changeInput('state', table.state()); + + // search info + var updateSearchInfo = function() { + changeInput('search', table.search()); + if (filterRow) changeInput('search_columns', filterRow.toArray().map(function(td) { + return $(td).find('input').first().val(); + })); + } + table.on('draw.dt', updateSearchInfo); + updateSearchInfo(); + + var cellInfo = function(thiz) { + var info = tweakCellIndex(table.cell(thiz)); + info.value = table.cell(thiz).data(); + return info; + } + // the current cell clicked on + table.on('click.dt', 'tbody td', function() { + changeInput('cell_clicked', cellInfo(this), null, null, {priority: 'event'}); + }) + changeInput('cell_clicked', {}); + + // do not trigger table selection when clicking on links unless they have classes + table.on('mousedown.dt', 'tbody td a', function(e) { + if (this.className === '') e.stopPropagation(); + }); + + methods.addRow = function(data, rowname, resetPaging) { + var n = table.columns().indexes().length, d = n - data.length; + if (d === 1) { + data = rowname.concat(data) + } else if (d !== 0) { + console.log(data); + console.log(table.columns().indexes()); + throw 'New data must be of the same length as current data (' + n + ')'; + }; + table.row.add(data).draw(resetPaging); + } + + methods.updateSearch = function(keywords) { + if (keywords.global !== null) + $(table.table().container()).find('input[type=search]').first() + .val(keywords.global).trigger('input'); + var columns = keywords.columns; + if (!filterRow || columns === null) return; + filterRow.toArray().map(function(td, i) { + var v = typeof columns === 'string' ? columns : columns[i]; + if (typeof v === 'undefined') { + console.log('The search keyword for column ' + i + ' is undefined') + return; + } + // Update column search string and values on linked filter widgets. + // 'input' for factor and char filters, 'change' for numeric filters. + $(td).find('input').first().val(v).trigger('input', [true]).trigger('change'); + }); + table.draw(); + } + + methods.hideCols = function(hide, reset) { + if (reset) table.columns().visible(true, false); + table.columns(hide).visible(false); + } + + methods.showCols = function(show, reset) { + if (reset) table.columns().visible(false, false); + table.columns(show).visible(true); + } + + methods.colReorder = function(order, origOrder) { + table.colReorder.order(order, origOrder); + } + + methods.selectPage = function(page) { + if (table.page.info().pages < page || page < 1) { + throw 'Selected page is out of range'; + }; + table.page(page - 1).draw(false); + } + + methods.reloadData = function(resetPaging, clearSelection) { + // empty selections first if necessary + if (methods.selectRows && inArray('row', clearSelection)) methods.selectRows([]); + if (methods.selectColumns && inArray('column', clearSelection)) methods.selectColumns([]); + if (methods.selectCells && inArray('cell', clearSelection)) methods.selectCells([]); + table.ajax.reload(null, resetPaging); + } + + // update table filters (set new limits of sliders) + methods.updateFilters = function(newProps) { + // loop through each filter in the filter row + filterRow.each(function(i, td) { + var k = i; + if (filterRow.length > newProps.length) { + if (i === 0) return; // first column is row names + k = i - 1; + } + // Update the filters to reflect the updated data. + // Allow "falsy" (e.g. NULL) to signify a no-op. + if (newProps[k]) { + setFilterProps(td, newProps[k]); + } + }); + }; + + table.shinyMethods = methods; + }, + resize: function(el, width, height, instance) { + if (instance.data) this.renderValue(el, instance.data, instance); + + // dynamically adjust height if fillContainer = TRUE + if (instance.fillContainer) + this.fillAvailableHeight(el, height); + + this.adjustWidth(el); + }, + + // dynamically set the scroll body to fill available height + // (used with fillContainer = TRUE) + fillAvailableHeight: function(el, availableHeight) { + + // see how much of the table is occupied by header/footer elements + // and use that to compute a target scroll body height + var dtWrapper = $(el).find('div.dataTables_wrapper'); + var dtScrollBody = $(el).find($('div.dataTables_scrollBody')); + var framingHeight = dtWrapper.innerHeight() - dtScrollBody.innerHeight(); + var scrollBodyHeight = availableHeight - framingHeight; + + // we need to set `max-height` to none as datatables library now sets this + // to a fixed height, disabling the ability to resize to fill the window, + // as it will be set to a fixed 100px under such circumstances, e.g., RStudio IDE, + // or FlexDashboard + // see https://github.com/rstudio/DT/issues/951#issuecomment-1026464509 + dtScrollBody.css('max-height', 'none'); + // set the height + dtScrollBody.height(scrollBodyHeight + 'px'); + }, + + // adjust the width of columns; remove the hard-coded widths on table and the + // scroll header when scrollX/Y are enabled + adjustWidth: function(el) { + var $el = $(el), table = $el.data('datatable'); + if (table) table.columns.adjust(); + $el.find('.dataTables_scrollHeadInner').css('width', '') + .children('table').css('margin-left', ''); + } +}); + + if (!HTMLWidgets.shinyMode) return; + + Shiny.addCustomMessageHandler('datatable-calls', function(data) { + var id = data.id; + var el = document.getElementById(id); + var table = el ? $(el).data('datatable') : null; + if (!table) { + console.log("Couldn't find table with id " + id); + return; + } + + var methods = table.shinyMethods, call = data.call; + if (methods[call.method]) { + methods[call.method].apply(table, call.args); + } else { + console.log("Unknown method " + call.method); + } + }); + +})(); diff --git a/docs/site_libs/datatables-css-0.0.0/datatables-crosstalk.css b/docs/site_libs/datatables-css-0.0.0/datatables-crosstalk.css new file mode 100644 index 000000000..bd1159c82 --- /dev/null +++ b/docs/site_libs/datatables-css-0.0.0/datatables-crosstalk.css @@ -0,0 +1,32 @@ +.dt-crosstalk-fade { + opacity: 0.2; +} + +html body div.DTS div.dataTables_scrollBody { + background: none; +} + + +/* +Fix https://github.com/rstudio/DT/issues/563 +If the `table.display` is set to "block" (e.g., pkgdown), the browser will display +datatable objects strangely. The search panel and the page buttons will still be +in full-width but the table body will be "compact" and shorter. +In therory, having this attributes will affect `dom="t"` +with `display: block` users. But in reality, there should be no one. +We may remove the below lines in the future if the upstream agree to have this there. +See https://github.com/DataTables/DataTablesSrc/issues/160 +*/ + +table.dataTable { + display: table; +} + + +/* +When DTOutput(fill = TRUE), it receives a .html-fill-item class (via htmltools::bindFillRole()), which effectively amounts to `flex: 1 1 auto`. That's mostly fine, but the case where `fillContainer=TRUE`+`height:auto`+`flex-basis:auto` and the container (e.g., a bslib::card()) doesn't have a defined height is a bit problematic since the table wants to fit the parent but the parent wants to fit the table, which results pretty small table height (maybe because there is a minimum height somewhere?). It seems better in this case to impose a 400px height default for the table, which we can do by setting `flex-basis` to 400px (the table is still allowed to grow/shrink when the container has an opinionated height). +*/ + +.html-fill-container > .html-fill-item.datatables { + flex-basis: 400px; +} diff --git a/docs/site_libs/dt-core-1.13.6/css/jquery.dataTables.extra.css b/docs/site_libs/dt-core-1.13.6/css/jquery.dataTables.extra.css new file mode 100644 index 000000000..b2dd141f4 --- /dev/null +++ b/docs/site_libs/dt-core-1.13.6/css/jquery.dataTables.extra.css @@ -0,0 +1,28 @@ +/* Selected rows/cells */ +table.dataTable tr.selected td, table.dataTable td.selected { + background-color: #b0bed9 !important; +} +/* In case of scrollX/Y or FixedHeader */ +.dataTables_scrollBody .dataTables_sizing { + visibility: hidden; +} + +/* The datatables' theme CSS file doesn't define +the color but with white background. It leads to an issue that +when the HTML's body color is set to 'white', the user can't +see the text since the background is white. One case happens in the +RStudio's IDE when inline viewing the DT table inside an Rmd file, +if the IDE theme is set to "Cobalt". + +See https://github.com/rstudio/DT/issues/447 for more info + +This fixes should have little side-effects because all the other elements +of the default theme use the #333 font color. + +TODO: The upstream may use relative colors for both the table background +and the color. It means the table can display well without this patch +then. At that time, we need to remove the below CSS attributes. +*/ +div.datatables { + color: #333; +} diff --git a/docs/site_libs/dt-core-1.13.6/css/jquery.dataTables.min.css b/docs/site_libs/dt-core-1.13.6/css/jquery.dataTables.min.css new file mode 100644 index 000000000..ad59f8438 --- /dev/null +++ b/docs/site_libs/dt-core-1.13.6/css/jquery.dataTables.min.css @@ -0,0 +1 @@ +:root{--dt-row-selected: 13, 110, 253;--dt-row-selected-text: 255, 255, 255;--dt-row-selected-link: 9, 10, 11;--dt-row-stripe: 0, 0, 0;--dt-row-hover: 0, 0, 0;--dt-column-ordering: 0, 0, 0;--dt-html-background: white}:root.dark{--dt-html-background: rgb(33, 37, 41)}table.dataTable td.dt-control{text-align:center;cursor:pointer}table.dataTable td.dt-control:before{display:inline-block;color:rgba(0, 0, 0, 0.5);content:"►"}table.dataTable tr.dt-hasChild td.dt-control:before{content:"▼"}html.dark table.dataTable td.dt-control:before{color:rgba(255, 255, 255, 0.5)}html.dark table.dataTable tr.dt-hasChild td.dt-control:before{color:rgba(255, 255, 255, 0.5)}table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting_asc_disabled,table.dataTable thead>tr>th.sorting_desc_disabled,table.dataTable thead>tr>td.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting_asc_disabled,table.dataTable thead>tr>td.sorting_desc_disabled{cursor:pointer;position:relative;padding-right:26px}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after{position:absolute;display:block;opacity:.125;right:10px;line-height:9px;font-size:.8em}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:before{bottom:50%;content:"▲";content:"▲"/""}table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:after{top:50%;content:"▼";content:"▼"/""}table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:after{opacity:.6}table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting_asc_disabled:before{display:none}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}div.dataTables_scrollBody>table.dataTable>thead>tr>th:before,div.dataTables_scrollBody>table.dataTable>thead>tr>th:after,div.dataTables_scrollBody>table.dataTable>thead>tr>td:before,div.dataTables_scrollBody>table.dataTable>thead>tr>td:after{display:none}div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:2px}div.dataTables_processing>div:last-child{position:relative;width:80px;height:15px;margin:1em auto}div.dataTables_processing>div:last-child>div{position:absolute;top:0;width:13px;height:13px;border-radius:50%;background:rgb(13, 110, 253);background:rgb(var(--dt-row-selected));animation-timing-function:cubic-bezier(0, 1, 1, 0)}div.dataTables_processing>div:last-child>div:nth-child(1){left:8px;animation:datatables-loader-1 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(2){left:8px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(3){left:32px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(4){left:56px;animation:datatables-loader-3 .6s infinite}@keyframes datatables-loader-1{0%{transform:scale(0)}100%{transform:scale(1)}}@keyframes datatables-loader-3{0%{transform:scale(1)}100%{transform:scale(0)}}@keyframes datatables-loader-2{0%{transform:translate(0, 0)}100%{transform:translate(24px, 0)}}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th,table.dataTable thead td,table.dataTable tfoot th,table.dataTable tfoot td{text-align:left}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable>thead>tr>th,table.dataTable>thead>tr>td{padding:10px;border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable>thead>tr>th:active,table.dataTable>thead>tr>td:active{outline:none}table.dataTable>tfoot>tr>th,table.dataTable>tfoot>tr>td{padding:10px 10px 6px 10px;border-top:1px solid rgba(0, 0, 0, 0.3)}table.dataTable tbody tr{background-color:transparent}table.dataTable tbody tr.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.9);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.9);color:rgb(255, 255, 255);color:rgb(var(--dt-row-selected-text))}table.dataTable tbody tr.selected a{color:rgb(9, 10, 11);color:rgb(var(--dt-row-selected-link))}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border>tbody>tr>th,table.dataTable.row-border>tbody>tr>td,table.dataTable.display>tbody>tr>th,table.dataTable.display>tbody>tr>td{border-top:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.row-border>tbody>tr:first-child>th,table.dataTable.row-border>tbody>tr:first-child>td,table.dataTable.display>tbody>tr:first-child>th,table.dataTable.display>tbody>tr:first-child>td{border-top:none}table.dataTable.row-border>tbody>tr.selected+tr.selected>td,table.dataTable.display>tbody>tr.selected+tr.selected>td{border-top-color:#0262ef}table.dataTable.cell-border>tbody>tr>th,table.dataTable.cell-border>tbody>tr>td{border-top:1px solid rgba(0, 0, 0, 0.15);border-right:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border>tbody>tr>th:first-child,table.dataTable.cell-border>tbody>tr>td:first-child{border-left:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border>tbody>tr:first-child>th,table.dataTable.cell-border>tbody>tr:first-child>td{border-top:none}table.dataTable.stripe>tbody>tr.odd>*,table.dataTable.display>tbody>tr.odd>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.023);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.023)}table.dataTable.stripe>tbody>tr.odd.selected>*,table.dataTable.display>tbody>tr.odd.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.923);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.923)}table.dataTable.hover>tbody>tr:hover>*,table.dataTable.display>tbody>tr:hover>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.035);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.035)}table.dataTable.hover>tbody>tr.selected:hover>*,table.dataTable.display>tbody>tr.selected:hover>*{box-shadow:inset 0 0 0 9999px #0d6efd !important;box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 1) !important}table.dataTable.order-column>tbody tr>.sorting_1,table.dataTable.order-column>tbody tr>.sorting_2,table.dataTable.order-column>tbody tr>.sorting_3,table.dataTable.display>tbody tr>.sorting_1,table.dataTable.display>tbody tr>.sorting_2,table.dataTable.display>tbody tr>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.019)}table.dataTable.order-column>tbody tr.selected>.sorting_1,table.dataTable.order-column>tbody tr.selected>.sorting_2,table.dataTable.order-column>tbody tr.selected>.sorting_3,table.dataTable.display>tbody tr.selected>.sorting_1,table.dataTable.display>tbody tr.selected>.sorting_2,table.dataTable.display>tbody tr.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.919)}table.dataTable.display>tbody>tr.odd>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.054);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.054)}table.dataTable.display>tbody>tr.odd>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.047);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.047)}table.dataTable.display>tbody>tr.odd>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.039);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.039)}table.dataTable.display>tbody>tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.954);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.954)}table.dataTable.display>tbody>tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.947);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.947)}table.dataTable.display>tbody>tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.939);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.939)}table.dataTable.display>tbody>tr.even>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.019)}table.dataTable.display>tbody>tr.even>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.011);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.011)}table.dataTable.display>tbody>tr.even>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.003);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.003)}table.dataTable.display>tbody>tr.even.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.919)}table.dataTable.display>tbody>tr.even.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.911);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.911)}table.dataTable.display>tbody>tr.even.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.903);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.903)}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.082);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.082)}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.074);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.074)}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.062);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.062)}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.982);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.982)}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.974);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.974)}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.962);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.962)}table.dataTable.no-footer{border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable.compact thead th,table.dataTable.compact thead td,table.dataTable.compact tfoot th,table.dataTable.compact tfoot td,table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px}table.dataTable th,table.dataTable td{box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_length select{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;color:inherit;padding:4px}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;color:inherit;margin-left:3px}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;color:inherit !important;border:1px solid transparent;border-radius:2px;background:transparent}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:inherit !important;border:1px solid rgba(0, 0, 0, 0.3);background-color:rgba(0, 0, 0, 0.05);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 230, 230, 0.05)), color-stop(100%, rgba(0, 0, 0, 0.05)));background:-webkit-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:-moz-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:-ms-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:-o-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:linear-gradient(to bottom, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#111;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%, #111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#0c0c0c;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:inherit}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td{vertical-align:middle}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid rgba(0, 0, 0, 0.3)}.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,.dataTables_wrapper.no-footer div.dataTables_scrollBody>table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width: 767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:.5em}}@media screen and (max-width: 640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:.5em}}html.dark{--dt-row-hover: 255, 255, 255;--dt-row-stripe: 255, 255, 255;--dt-column-ordering: 255, 255, 255}html.dark table.dataTable>thead>tr>th,html.dark table.dataTable>thead>tr>td{border-bottom:1px solid rgb(89, 91, 94)}html.dark table.dataTable>thead>tr>th:active,html.dark table.dataTable>thead>tr>td:active{outline:none}html.dark table.dataTable>tfoot>tr>th,html.dark table.dataTable>tfoot>tr>td{border-top:1px solid rgb(89, 91, 94)}html.dark table.dataTable.row-border>tbody>tr>th,html.dark table.dataTable.row-border>tbody>tr>td,html.dark table.dataTable.display>tbody>tr>th,html.dark table.dataTable.display>tbody>tr>td{border-top:1px solid rgb(64, 67, 70)}html.dark table.dataTable.row-border>tbody>tr.selected+tr.selected>td,html.dark table.dataTable.display>tbody>tr.selected+tr.selected>td{border-top-color:#0257d5}html.dark table.dataTable.cell-border>tbody>tr>th,html.dark table.dataTable.cell-border>tbody>tr>td{border-top:1px solid rgb(64, 67, 70);border-right:1px solid rgb(64, 67, 70)}html.dark table.dataTable.cell-border>tbody>tr>th:first-child,html.dark table.dataTable.cell-border>tbody>tr>td:first-child{border-left:1px solid rgb(64, 67, 70)}html.dark .dataTables_wrapper .dataTables_filter input,html.dark .dataTables_wrapper .dataTables_length select{border:1px solid rgba(255, 255, 255, 0.2);background-color:var(--dt-html-background)}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.current,html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{border:1px solid rgb(89, 91, 94);background:rgba(255, 255, 255, 0.15)}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.disabled,html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{color:#666 !important}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button:hover{border:1px solid rgb(53, 53, 53);background:rgb(53, 53, 53)}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button:active{background:#3a3a3a} diff --git a/docs/site_libs/dt-core-1.13.6/js/jquery.dataTables.min.js b/docs/site_libs/dt-core-1.13.6/js/jquery.dataTables.min.js new file mode 100644 index 000000000..f786b0da8 --- /dev/null +++ b/docs/site_libs/dt-core-1.13.6/js/jquery.dataTables.min.js @@ -0,0 +1,4 @@ +/*! DataTables 1.13.6 + * ©2008-2023 SpryMedia Ltd - datatables.net/license + */ +!function(n){"use strict";var a;"function"==typeof define&&define.amd?define(["jquery"],function(t){return n(t,window,document)}):"object"==typeof exports?(a=require("jquery"),"undefined"==typeof window?module.exports=function(t,e){return t=t||window,e=e||a(t),n(e,t,t.document)}:n(a,window,window.document)):window.DataTable=n(jQuery,window,document)}(function(P,j,v,H){"use strict";function d(t){var e=parseInt(t,10);return!isNaN(e)&&isFinite(t)?e:null}function l(t,e,n){var a=typeof t,r="string"==a;return"number"==a||"bigint"==a||!!h(t)||(e&&r&&(t=$(t,e)),n&&r&&(t=t.replace(q,"")),!isNaN(parseFloat(t))&&isFinite(t))}function a(t,e,n){var a;return!!h(t)||(h(a=t)||"string"==typeof a)&&!!l(t.replace(V,"").replace(/ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+

Themes and Styles

+
+ + + +
+ + + + +
+ + + +
+ +
+

To customize the appearance of tables, modelsummary supports five of the most popular table-making packages:

+
    +
  1. tinytable: https://vincentarelbundock.github.io/tinytable/
  2. +
  3. gt: https://gt.rstudio.com
  4. +
  5. kableExtra: http://haozhu233.github.io/kableExtra
  6. +
  7. huxtable: https://hughjonesd.github.io/huxtable/
  8. +
  9. flextable: https://davidgohel.github.io/flextable/
  10. +
  11. DT: https://rstudio.github.io/DT
  12. +
+

Users are encouraged to visit these websites to determine which package suits their needs best.

+

To create customized tables, we proceed as follows:

+
    +
  1. Call a modelsummary function like datasummary().
  2. +
  3. Use the output argument to specify the package to be used for customization, such as output="tinytable" or output="gt".
  4. +
  5. Apply a function from the package in question to the object created by modelsummary.
  6. +
+

To illustrate, we download data from the Rdatasets repository and we estimate 5 models:

+
+
library(modelsummary)
+
+url <- "https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv"
+dat <- read.csv(url, na.strings = "")
+
+models <- list(
+    I = lm(Donations ~ Literacy, data = dat),
+    II = lm(Crime_pers ~ Literacy, data = dat),
+    III = lm(Crime_prop ~ Literacy + Clergy, data = dat),
+    IV = glm(Crime_pers ~ Literacy + Clergy, family = poisson, data = dat),
+    V = glm(Donations ~ Literacy + Clergy, family = poisson, data = dat)
+)
+
+

In the rest of this vignette, we will customize tables using tools tinytable and gt. The same process can be used to customize kableExtra, flextable, huxtable, and DT tables.

+

tinytable

+

The tinytable package offers many functions to customize the appearance of tables. Below, we give a couple illustrations, but interested readers should refer to the detailed tutorial on the tinytable package website: https://vincentarelbundock.github.io/tinytable/

+

In this example, we use the group_tt() function to add spanning column headers, and the style_tt() function to color a few cells of the table:

+
+
library(tinytable)
+
+modelsummary(models) |>
+    group_tt(j = list(Linear = 2:4, Poisson = 5:6)) |>
+    style_tt(i = 3:4, j = 2, background = "teal", color = "white", bold = TRUE)
+
+ + + + + +tinytable_qn47drujfjv4mwrywsfm + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LinearPoisson
IIIIIIIVV
(Intercept)8759.068 20357.309 11243.544 9.708 8.986
(1559.363)(2020.980)(1011.240)(0.003) (0.004)
Literacy -42.886 -15.358 -68.507 0.000 -0.006
(36.362) (47.127) (18.029) (0.000) (0.000)
Clergy -16.376 0.004 0.002
(12.522) (0.000) (0.000)
Num.Obs. 86 86 86 86 86
R2 0.016 0.001 0.152
R2 Adj. 0.005 -0.011 0.132
AIC 1739.1 1783.7 1616.9 242266.3 302865.8
BIC 1746.5 1791.1 1626.7 242273.6 302873.2
Log.Lik. -866.574 -888.874 -804.441 -121130.130-151429.921
F 1.391 0.106 7.441 7905.811 4170.610
RMSE 5753.14 7456.23 2793.43 7233.22 5727.27
+
+ + +
+
+

Now, we create a descriptive statistics table with datasummary(). That table includes an emptyr row, which we fill with density plots using the plot_tt() function from tinytable:

+
+
Density <- function(x) ""
+
+datasummary(mpg + hp ~ Mean + SD + Density, data = mtcars) |>
+    plot_tt(
+        j = 4,
+        fun = "density",
+        data = list(mtcars$mpg, mtcars$hp),
+        color = "#E69F00")
+
+ + + + + +tinytable_zebwj88hhsoctkcajqbz + +
+ + + + + + + + + + + + + + + + + + + + + +
MeanSDDensity
mpg20.09 6.03
hp 146.6968.56
+
+ + +
+
+

HTML tables can be further customized in tinytable by specifying CSS rules. Again, detailed tutorials are available on the tinytable website. This example adds an image in the background of a table:

+
+
css <- "
+.mytable {
+  background-size: cover;
+  background-position: center;
+  background-image: url('https://user-images.githubusercontent.com/987057/82732352-b9aabf00-9cda-11ea-92a6-26750cf097d0.png');
+  --bs-table-bg: transparent;
+}
+"
+
+modelsummary(models) |>
+    style_tt(
+        bootstrap_class = "table table-borderless mytable", 
+        bootstrap_css_rule = css)
+
+ + + + + +tinytable_3rji1pvm1ucgp7uyvm1w + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IIIIIIIVV
(Intercept)8759.068 20357.309 11243.544 9.708 8.986
(1559.363)(2020.980)(1011.240)(0.003) (0.004)
Literacy -42.886 -15.358 -68.507 0.000 -0.006
(36.362) (47.127) (18.029) (0.000) (0.000)
Clergy -16.376 0.004 0.002
(12.522) (0.000) (0.000)
Num.Obs. 86 86 86 86 86
R2 0.016 0.001 0.152
R2 Adj. 0.005 -0.011 0.132
AIC 1739.1 1783.7 1616.9 242266.3 302865.8
BIC 1746.5 1791.1 1626.7 242273.6 302873.2
Log.Lik. -866.574 -888.874 -804.441 -121130.130-151429.921
F 1.391 0.106 7.441 7905.811 4170.610
RMSE 5753.14 7456.23 2793.43 7233.22 5727.27
+
+ + +
+
+

gt

+

To illustrate how to customize tables using the gt package we will use the following functions from the gt package:

+
    +
  • +tab_spanner creates labels to group columns.
  • +
  • +tab_footnote adds a footnote and a matching marking in a specific cell.
  • +
  • +tab_style can modify the text and color of rows, columns, or cells.
  • +
+

To produce a “cleaner” look, we will also use modelsummary’s stars, coef_map, gof_omit, and title arguments.

+

Note that in order to access gt functions, we must first load the library.

+
+
library(gt)
+
+## build table with `modelsummary` 
+cm <- c( '(Intercept)' = 'Constant', 'Literacy' = 'Literacy (%)', 'Clergy' = 'Priests/capita')
+cap <- 'A modelsummary table customized with gt'
+
+tab <- modelsummary(models, 
+                output = "gt",
+                coef_map = cm, stars = TRUE, 
+                title = cap, gof_omit = 'IC|Log|Adj') 
+
+## customize table with `gt`
+
+tab %>%
+
+    # column labels
+    tab_spanner(label = 'Donations', columns = 2:3) %>%
+    tab_spanner(label = 'Crimes (persons)', columns = 4:5) %>%
+    tab_spanner(label = 'Crimes (property)', columns = 6) %>%
+
+    # footnote
+    tab_footnote(footnote = md("A very **important** variable."),
+                 locations = cells_body(rows = 3, columns = 1)) %>%
+
+    # text and background color
+    tab_style(style = cell_text(color = 'red'),
+              locations = cells_body(rows = 3)) %>%
+    tab_style(style = cell_fill(color = 'lightblue'),
+              locations = cells_body(rows = 5))
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A modelsummary table customized with gt
+ Donations + + Crimes (persons) + + Crimes (property) +
IIIIIIIVV
Constant8759.068***20357.309***11243.544***9.708***8.986***
(1559.363)(2020.980)(1011.240)(0.003)(0.004)
Literacy (%)1 +-42.886-15.358-68.507***0.000***-0.006***
(36.362)(47.127)(18.029)(0.000)(0.000)
Priests/capita-16.3760.004***0.002***
(12.522)(0.000)(0.000)
Num.Obs.8686868686
R20.0160.0010.152
F1.3910.1067.4417905.8114170.610
RMSE5753.147456.232793.437233.225727.27
+ p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001
+1 A very important variable.
+
+
+
+

The gt website offers many more examples. The possibilities are endless. For instance, gt allows you to embed images in your tables using the text_transform and local_image functions:

+
+
f <- function(x) web_image(url = "https://user-images.githubusercontent.com/987057/82732352-b9aabf00-9cda-11ea-92a6-26750cf097d0.png", height = 80)
+
+tab %>% 
+    text_transform(locations = cells_body(columns = 2:6, rows = 1), fn = f)
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A modelsummary table customized with gt
IIIIIIIVV
Constant
(1559.363)(2020.980)(1011.240)(0.003)(0.004)
Literacy (%)-42.886-15.358-68.507***0.000***-0.006***
(36.362)(47.127)(18.029)(0.000)(0.000)
Priests/capita-16.3760.004***0.002***
(12.522)(0.000)(0.000)
Num.Obs.8686868686
R20.0160.0010.152
F1.3910.1067.4417905.8114170.610
RMSE5753.147456.232793.437233.225727.27
+ p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001
+
+
+
+
+

Themes

+

If you want to apply the same post-processing functions to your tables, you can use modelsummary’s theming functionality. To do so, we first create a function to post-process a table. This function must accept a table as its first argument, and include the ellipsis (...). Optionally, the theming function can also accept an hrule argument which is a vector of row positions where we insert horizontal rule, and an output_format which allows output format-specific customization. For inspiration, you may want to consult the default modelsummary themes in the themes.R file of the Github repository.

+

Once the theming function is created, we assign it to a global option called modelsummary_theme_kableExtra, modelsummary_theme_gt, modelsummary_theme_flextable, or modelsummary_theme_huxtable. For example, if you want to add row striping to all your gt tables:

+
+
library(gt)
+
+## The ... ellipsis is required!
+custom_theme <- function(x, ...) {
+    x %>% gt::opt_row_striping(row_striping = TRUE)
+}
+options("modelsummary_theme_gt" = custom_theme)
+
+mod <- lm(mpg ~ hp + drat, mtcars)
+modelsummary(mod, output = "gt")
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)10.790
(5.078)
hp-0.052
(0.009)
drat4.698
(1.192)
Num.Obs.32
R20.741
R2 Adj.0.723
AIC169.5
BIC175.4
Log.Lik.-80.752
F41.522
RMSE3.02
+
+
+
+
+
+
url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/palmerpenguins/penguins.csv'
+penguins <- read.csv(url, na.strings = "")
+
+datasummary_crosstab(island ~ sex * species, output = "gt", data = penguins)
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
islandfemale male All
AdelieChinstrapGentooAdelieChinstrapGentoo
BiscoeN2205822061168
% row13.10.034.513.10.036.3100.0
DreamN2734028340124
% row21.827.40.022.627.40.0100.0
TorgersenN2400230052
% row46.20.00.044.20.00.0100.0
AllN733458733461344
% row21.29.916.921.29.917.7100.0
+
+
+
+
+

Restore default theme:

+
+
options("modelsummary_theme_gt" = NULL)
+
+

Themes: Data Frame

+

A particularly flexible strategy is to apply a theme to the dataframe output format. To illustrate, recall that setting output="dataframe" produces a data frame with a lot of extraneous meta information. To produce a nice table, we have to process that output a bit:

+
+
mod <- lm(mpg ~ hp + drat, mtcars)
+
+modelsummary(mod, output = "dataframe")
+
+
        part        term statistic     (1)
+1  estimates (Intercept)  estimate  10.790
+2  estimates (Intercept) std.error (5.078)
+3  estimates          hp  estimate  -0.052
+4  estimates          hp std.error (0.009)
+5  estimates        drat  estimate   4.698
+6  estimates        drat std.error (1.192)
+7        gof    Num.Obs.                32
+8        gof          R2             0.741
+9        gof     R2 Adj.             0.723
+10       gof         AIC             169.5
+11       gof         BIC             175.4
+12       gof    Log.Lik.           -80.752
+13       gof           F            41.522
+14       gof        RMSE              3.02
+
+
+

modelsummary supports the DT table-making package out of the box. But for the sake of illustration, imagine we want to create a table using the DT package with specific customization and options, in a repeatable fashion. To do this, we can create a theming function:

+
+
library(DT)
+
+theme_df <- function(tab) {
+    out <- tab
+    out$term[out$statistic == "modelsummary_tmp2"] <- " "
+    out$part <- out$statistic <- NULL
+    colnames(out)[1] <- " "
+    datatable(out, rownames = FALSE,
+              options = list(pageLength = 30))
+}
+
+options("modelsummary_theme_dataframe" = theme_df)
+modelsummary(mod, output = "dataframe")
+
+
+ +
+
+

Restore default theme:

+
+
options("modelsummary_theme_dataframe" = NULL)
+
+

Variable labels

+

Some packages like haven can assign attributes to the columns of a dataset for use as labels. Most of the functions in modelsummary can display these labels automatically. For example:

+
+
library(haven)
+dat <- mtcars
+dat$am <- haven::labelled(dat$am, label = "Transmission")
+dat$mpg <- haven::labelled(dat$mpg, label = "Miles per Gallon")
+mod <- lm(hp ~ mpg + am, dat = dat)
+
+modelsummary(mod, coef_rename = TRUE)
+
+ + + + + +tinytable_arqfhbpjlg6yswk89tpk + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept) 352.312
(27.226)
Miles per Gallon-11.200
(1.494)
Transmission 47.725
(18.048)
Num.Obs. 32
R2 0.680
R2 Adj. 0.658
AIC 331.9
BIC 337.8
Log.Lik. -161.971
F 30.766
RMSE 38.19
+
+ + +
+
datasummary_skim(dat[, c("mpg", "am", "drat")])
+
+ + + + + +tinytable_x36ahw3k7w1vv6u83si4 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UniqueMissing Pct.MeanSDMinMedianMaxHistogram
Miles per Gallon25020.16.010.419.233.9
Transmission200.40.50.00.01.0
drat2203.60.52.83.74.9
+
+ + +
+
+

Warning: Saving to file

+

When users supply a file name to the output argument, the table is written immediately to file. This means that users cannot post-process and customize the resulting table using functions from gt, kableExtra, huxtable, or flextable. When users specify a filename in the output argument, the modelsummary() call should be the final one in the chain.

+

This is OK:

+
+
modelsummary(models, output = 'table.html')
+
+

This is not OK:

+
+
library(tinytable)
+modelsummary(models, output = 'table.html') |>
+    group_tt(j = list(Literacy = 2:3))
+
+

To save a customized table, you should apply all the customizations you need before saving it using dedicated package-specific functions:

+ +

For example, to add color column spanners with the gt package:

+
+
library(tinytable)
+modelsummary(models, output = 'tinytable') |>
+    group_tt(j = list(Literacy = 2:3)) |>
+    save_tt("table.html")
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/vignettes/datasummary.html b/docs/vignettes/datasummary.html new file mode 100644 index 000000000..2f7d8bbd9 --- /dev/null +++ b/docs/vignettes/datasummary.html @@ -0,0 +1,8768 @@ + + + + + + +modelsummary: Data and Model Summaries in R – Data Summaries + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+

Data Summaries

+
+ + + +
+ + + + +
+ + + +
+ +
+

datasummary is a function from the modelsummary package. It allows us to create data summaries, frequency tables, crosstabs, correlation tables, balance tables (aka “Table 1”), and more. It has many benefits:

+
    +
  • Easy to use.
  • +
  • +Extremely flexible.
  • +
  • Many output formats: HTML, LaTeX, Microsoft Word and Powerpoint, Text/Markdown, PDF, RTF, or Image files.
  • +
  • Embed tables in Rmarkdown or knitr dynamic documents.
  • +
  • +Customize the appearance of tables with the tinytable, gt, kableExtra or flextable packages. The possibilities are endless!
  • +
+

This tutorial will show how to draw tables like these (and more!):

+
+ +
+

datasummary is built around the fantastic tables package for R. It is a thin “wrapper” which adds convenience functions and arguments; a user-interface consistent with modelsummary; cleaner html output; and the ability to export tables to more formats, including gt tables, flextable objects, and Microsoft Word documents.

+

datasummary is a general-purpose table-making tool. It allows us to build (nearly) any summary table we want by using simple 2-sided formulae. For example, in the expression x + y ~ mean + sd, the left-hand side of the formula identifies the variables or statistics to display as rows, and the right-hand side defines the columns. Below, we will see how variables and statistics can be “nested” with the * operator to produce tables like the ones above.

+

In addition to datasummary, the modelsummary package includes a “family” of companion functions named datasummary_*. These functions facilitate the production of standard, commonly used tables. This family currently includes:

+ +

In the next three sections, we illustrate how to use datasummary_balance, datasummary_correlation, datasummary_skim, and datasummary_crosstab. Then, we dive into datasummary itself to highlight its ease and flexibility.

+

datasummary_skim

+

The first datasummary companion function is called datasummary_skim. It was heavily inspired by one of my favorite data exploration tools for R: the skimr package. The goal of this function is to give us a quick look at the data.

+

To illustrate, we download data from the cool new palmerpenguins package by Alison Presmanes Hill and Allison Horst. These data were collected at the Palmer Station in Antarctica by Gorman, Williams & Fraser (2014), and they include 3 categorical variables and 4 numeric variables.

+
+
library(modelsummary)
+library(tidyverse)
+
+url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/palmerpenguins/penguins.csv'
+penguins <- read.csv(url, na.strings = "")
+
+

To summarize the numeric variables in the dataset, we type:

+
+ +
+
Warning: The `replace_na` argument was renamed `replace`.
+
+
+ + + + + +tinytable_5hze935za5v10ggcr8mt + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UniqueMissing Pct.MeanSDMinMedianMaxHistogram
rownames3440172.599.41.0172.5344.0
bill_length_mm165143.95.532.144.559.6
bill_depth_mm81117.22.013.117.321.5
flipper_length_mm561200.914.1172.0197.0231.0
body_mass_g9514201.8802.02700.04050.06300.0
year302008.00.82007.02008.02009.0
N%
speciesAdelie15244.2
Chinstrap6819.8
Gentoo12436.0
islandBiscoe16848.8
Dream12436.0
Torgersen5215.1
sexfemale16548.0
male16848.8
NA113.2
+
+ + +
+
+

To summarize the categorical variables in the dataset, we type:

+
+
datasummary_skim(penguins, type = "categorical")
+
+ + + + + +tinytable_21st35omfio8kv9i6se7 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
N%
speciesAdelie 15244.2
Chinstrap68 19.8
Gentoo 12436.0
island Biscoe 16848.8
Dream 12436.0
Torgersen52 15.1
sex female 16548.0
male 16848.8
NA 11 3.2
+
+ + +
+
+

datasummary_balance

+

The expressions “balance table” or “Table 1” refer to a type of table which is often printed in the opening pages of a scientific peer-reviewed article. Typically, this table includes basic descriptive statistics about different subsets of the study population. For instance, analysts may want to compare the socio-demographic characteristics of members of the “control” and “treatment” groups in a randomized control trial, or the flipper lengths of male and female penguins. In addition, balance tables often include difference in means tests.

+

To illustrate how to build a balance table using the datasummary_balance function, we download data about a job training experiment studies in Lalonde (1986). Then, we clean up the data by renaming and recoding a few variables.

+
+
# Download and read data
+training <- 'https://vincentarelbundock.github.io/Rdatasets/csv/Ecdat/Treatment.csv'
+training <- read.csv(training, na.strings = "")
+
+# Rename and recode variables
+training <- training %>%
+            mutate(`Earnings Before` = re75 / 1000,
+                   `Earnings After` = re78 / 1000,
+                   Treatment = ifelse(treat == TRUE, 'Treatment', 'Control'),
+                   Married = ifelse(married == TRUE, 'Yes', 'No')) %>%
+            select(`Earnings Before`,
+                   `Earnings After`,
+                   Treatment,
+                   Ethnicity = ethn,
+                   Age = age,
+                   Education = educ,
+                   Married)
+
+

Now, we execute the datasummary_balance function. If the estimatr package is installed, datasummary_balance will calculate the difference in means and test statistics.

+
+
caption <- 'Descriptive statistics about participants in a job training experiment. The earnings are displayed in 1000s of USD. This table was created using the "datasummary" function from the "modelsummary" package for R.'
+reference <- 'Source: Lalonde (1986) American Economic Review.'
+
+library(modelsummary)
+datasummary_balance(~Treatment,
+                    data = training,
+                    title = caption,
+                    notes = reference)
+
+

Note that if the dataset includes columns called “blocks”, “clusters”, or “weights”, this information will automatically be taken into consideration by estimatr when calculating the difference in means and the associated statistics.

+

Users can also use the ~ 1 formula to indicate that they want to summarize all the data instead of splitting the analysis across subgroups:

+
+
datasummary_balance(~ 1, data = training)
+
+ + + + + +tinytable_wpk0gw977w3n22g5zk08 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MeanStd. Dev.
Earnings Before 17.913.9
Earnings After 20.515.6
Age 34.210.5
Education 12.03.1
N Pct.
Treatment Control 249093.1
Treatment185 6.9
Ethnicity black 780 29.2
hispanic 92 3.4
other 180367.4
Married No 483 18.1
Yes 219281.9
+
+ + +
+
+

datasummary_correlation

+

The datasummary_correlation accepts a dataframe or tibble, it identifies all the numeric variables, and calculates the correlation between each of those variables:

+
+ +
+ + + + + +tinytable_6xiba1th3u8b06aoqow2 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mpgcyldisphpdratwtqsecvsamgearcarb
mpg 1 . . . . . . . . . .
cyl -.851 . . . . . . . . .
disp-.85.90 1 . . . . . . . .
hp -.78.83 .79 1 . . . . . . .
drat.68 -.70-.71-.451 . . . . . .
wt -.87.78 .89 .66 -.711 . . . . .
qsec.42 -.59-.43-.71.09 -.171 . . . .
vs .66 -.81-.71-.72.44 -.55.74 1 . . .
am .60 -.52-.59-.24.71 -.69-.23.17 1 . .
gear.48 -.49-.56-.13.70 -.58-.21.21 .791 .
carb-.55.53 .39 .75 -.09.43 -.66-.57.06.271
+
+ + +
+
+

The values displayed in this table are equivalent to those obtained by calling: cor(x, use='pairwise.complete.obs').

+

The datasummary_correlation function has a methods argument. The default value is "pearson", but it also accepts other values like "spearman". In addition, method can accept any function which takes a data frame and returns a matrix. For example, we can create a custom function to display information from the correlation package. This allows us to include significance stars even if the stars argument is not supported by default in datasummary_correlation():

+
+
library(correlation)
+
+fun <- function(x) {
+  out <- correlation(mtcars) |>
+    summary() |>
+    format(2) |> 
+    as.matrix()
+  row.names(out) <- out[, 1]
+  out <- out[, 2:ncol(out)]
+  return(out)
+}
+
+datasummary_correlation(mtcars, method = fun)
+
+ + + + + +tinytable_5a6xio01ay0a59vgg4fg + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
carbgearamvsqsecwtdrathpdispcyl
mpg -.55* .48 .60** .66** .42 -.87***.68*** -.78***-.85***-.85***
cyl .53* -.49 -.52* -.81***-.59* .78*** -.70***.83*** .90***
disp.39 -.56* -.59* -.71***-.43 .89*** -.71***.79***
hp .75***-.13 -.24 -.72***-.71***.66** -.45
drat-.09 .70***.71*** .44 .09 -.71***
wt .43 -.58* -.69***-.55* -.17
qsec-.66**-.21 -.23 .74***
vs -.57* .21 .17
am .06 .79***
gear.27
+
+ + +
+
+

datasummary_crosstab

+

A cross tabulation is often useful to explore the association between two categorical variables.

+
+
library(modelsummary)
+url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/palmerpenguins/penguins.csv'
+penguins <- read.csv(url, na.strings = "")
+
+datasummary_crosstab(species ~ sex, data = penguins)
+
+ + + + + +tinytable_ef6w5jijjcx0q2iohra7 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
species femalemaleAll
Adelie N 73 73 152
% row48.048.0100.0
ChinstrapN 34 34 68
% row50.050.0100.0
Gentoo N 58 61 124
% row46.849.2100.0
All N 165 168 344
% row48.048.8100.0
+
+ + +
+
+

You can create multi-level crosstabs by specifying interactions using the * operator:

+
+
datasummary_crosstab(species ~ sex * island, data = penguins)
+
+ + + + + +tinytable_v1g960cknp04mxigu84q + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
femalemale
species BiscoeDreamTorgersenBiscoeDreamTorgersenAll
Adelie N 22 27 24 22 28 23 152
% row14.517.815.814.518.415.1100.0
ChinstrapN 0 34 0 0 34 0 68
% row0.0 50.00.0 0.0 50.00.0 100.0
Gentoo N 58 0 0 61 0 0 124
% row46.80.0 0.0 49.20.0 0.0 100.0
All N 80 61 24 83 62 23 344
% row23.317.77.0 24.118.06.7 100.0
+
+ + +
+
+

By default, the cell counts and row percentages are shown for each cell, and both row and column totals are calculated. To show cell percentages or column percentages, or to drop row and column totals, adjust the statistic argument. This argument accepts a formula that follows the datasummary “language”. To understand exactly how it works, you may find it useful to skip to the datasummary tutorial in the next section. Example:

+
+
datasummary_crosstab(species ~ sex,
+                     statistic = 1 ~ Percent("col"),
+                     data = penguins)
+
+ + + + + +tinytable_r1kt8kcwahmvwlmzos05 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
species femalemale
Adelie % col44.2 43.5
Chinstrap% col20.6 20.2
Gentoo % col35.2 36.3
All % col100.0100.0
+
+ + +
+
+

See ?datasummary_crosstab for more details.

+

datasummary

+

datasummary tables are specified using a 2-sided formula, divided by a tilde ~. The left-hand side describes the rows; the right-hand side describes the columns. To illustrate how this works, we will again be using the palmerpenguins dataset:

+

To display the flipper_length_mm variable as a row and the mean as a column, we type:

+
+
datasummary(flipper_length_mm ~ Mean,
+            data = penguins)
+
+ + + + + +tinytable_u2unxe9sbpvb8h7x740s + +
+ + + + + + + + + +
Mean
flipper_length_mm200.92
+
+ + +
+
+

To flip rows and columns, we flip the left and right-hand sides of the formula:

+
+
datasummary(Mean ~ flipper_length_mm,
+            data = penguins)
+
+ + + + + +tinytable_vllsch432ouhiu1wg2mk + +
+ + + + + + + + + +
flipper_length_mm
Mean200.92
+
+ + +
+
+

Custom summary functions

+

The Mean function is a shortcut supplied by modelsummary, and it is equivalent to mean(x,na.rm=TRUE). Since the flipper_length_mm variable includes missing observation, using the mean formula (with default na.rm=FALSE) would produce a missing/empty cell:

+
+
datasummary(flipper_length_mm ~ mean,
+            data = penguins)
+
+ + + + + +tinytable_gmkbnknsg9dbs7d4wso2 + +
+ + + + + + + + + +
mean
flipper_length_mm
+
+ + +
+
+

modelsummary supplies these functions: Mean, SD, Min, Max, Median, P0, P25, P50, P75, P100, Histogram, and a few more (see the package documentation).

+

Users are also free to create and use their own custom summaries. Any R function which takes a vector and produces a single value is acceptable. For example, the Range functions return a numerical value, and the MinMax returns a string:

+
+
Range <- function(x) max(x, na.rm = TRUE) - min(x, na.rm = TRUE)
+
+datasummary(flipper_length_mm ~ Range,
+            data = penguins)
+
+ + + + + +tinytable_j1e99w0p98bh76b91fco + +
+ + + + + + + + + +
Range
flipper_length_mm59.00
+
+ + +
+
MinMax <- function(x) paste0('[', min(x, na.rm = TRUE), ', ', max(x, na.rm = TRUE), ']')
+
+datasummary(flipper_length_mm ~ MinMax,
+            data = penguins)
+
+ + + + + +tinytable_m6msntnnf9fp8e82tas5 + +
+ + + + + + + + + +
MinMax
flipper_length_mm[172, 231]
+
+ + +
+
+

Concatenating with + +

+

To include more rows and columns, we use the + sign:

+
+
datasummary(flipper_length_mm + body_mass_g ~ Mean + SD,
+            data = penguins)
+
+ + + + + +tinytable_jz9odiw0rb1tprw7356f + +
+ + + + + + + + + + + + + + + + + + +
MeanSD
flipper_length_mm200.92 14.06
body_mass_g 4201.75801.95
+
+ + +
+
+

Sometimes, it can be cumbersome to list all variables separated by + signs. The All() function is a useful shortcut:

+
+
datasummary(All(penguins) ~ Mean + SD,
+            data = penguins)
+
+ + + + + +tinytable_fpe8szyir8ebc9hoqajp + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MeanSD
rownames 172.50 99.45
bill_length_mm 43.92 5.46
bill_depth_mm 17.15 1.97
flipper_length_mm200.92 14.06
body_mass_g 4201.75801.95
year 2008.030.82
+
+ + +
+
+

By default, All selects all numeric variables. This behavior can be changed by modifying the function’s arguments. See ?All for details.

+

Nesting with * +

+

datasummary can nest variables and statistics inside categorical variables using the * symbol. When applying the the * operator to factor, character, or logical variables, columns or rows will automatically be nested. For instance, if we want to display separate means for each value of the variable sex, we use mean * sex:

+
+
datasummary(flipper_length_mm + body_mass_g ~ mean * sex,
+            data = penguins)
+
+ + + + + +tinytable_5hc3q270kk17d3xu3iq8 + +
+ + + + + + + + + + + + + + + + + + +
femalemale
flipper_length_mm197.36 204.51
body_mass_g 3862.274545.68
+
+ + +
+
+

We can use parentheses to nest several terms inside one another, using a call of this form: x * (y + z). Here is an example with nested columns:

+
+
datasummary(body_mass_g ~ sex * (mean + sd),
+            data = penguins)
+
+ + + + + +tinytable_cilcylzojaj6eqe8vwnn + +
+ + + + + + + + + + + + + + + + + + + + + + +
femalemale
meansdmeansd
body_mass_g3862.27666.174545.68787.63
+
+ + +
+
+

Here is an example with nested rows:

+
+
datasummary(sex * (body_mass_g + flipper_length_mm) ~ mean + sd,
+            data = penguins)
+
+ + + + + +tinytable_w27wjhsaw7brd2zo6xv3 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sex meansd
femalebody_mass_g 3862.27666.17
flipper_length_mm197.36 12.50
male body_mass_g 4545.68787.63
flipper_length_mm204.51 14.55
+
+ + +
+
+

The order in which terms enter the formula determines the order in which labels are displayed. For example, this shows island above sex:

+
+
datasummary(flipper_length_mm + body_mass_g ~ mean * island * sex,
+            data = penguins)
+
+ + + + + +tinytable_0z11rz6aqhv67q2ggqx9 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BiscoeDreamTorgersen
femalemalefemalemalefemalemale
flipper_length_mm205.69 213.29 190.02 196.31 188.29 194.91
body_mass_g 4319.385104.523446.313987.103395.834034.78
+
+ + +
+
+

This shows sex above island values:

+
+
datasummary(flipper_length_mm + body_mass_g ~ mean * sex * island,
+            data = penguins)
+
+ + + + + +tinytable_a9g5byj5w3m2p0phaqp5 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
femalemale
BiscoeDreamTorgersenBiscoeDreamTorgersen
flipper_length_mm205.69 190.02 188.29 213.29 196.31 194.91
body_mass_g 4319.383446.313395.835104.523987.104034.78
+
+ + +
+
+

By default, datasummary omits column headers with a single value/label across all columns, except for the header that sits just above the data. If the header we want to see is not displayed, we may want to reorder the terms of the formula. To show all headers, set sparse_header=FALSE:

+
+
datasummary(flipper_length_mm + body_mass_g ~ mean * sex * island,
+            data = penguins,
+            sparse_header = FALSE)
+
+ + + + + +tinytable_o3ai0bv4e07vt7pt6iez + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
femalemale
BiscoeDreamTorgersenBiscoeDreamTorgersen
flipper_length_mm205.69 190.02 188.29 213.29 196.31 194.91
body_mass_g 4319.383446.313395.835104.523987.104034.78
+
+ + +
+
+

When using sparse_header=FALSE, it is often useful to insert Heading() * in the table formula, in order to rename or omit some of the labels manually. Type ?tables::Heading for details and examples.

+

Renaming with = +

+

Personally, I prefer to rename variables and values before drawing my tables, using backticks when variable names include whitespace. For example,

+
+
tmp <- penguins %>%
+       select(`Flipper length (mm)` = flipper_length_mm,
+              `Body mass (g)` = body_mass_g)
+
+datasummary(`Flipper length (mm)` + `Body mass (g)` ~ Mean + SD,
+            data = tmp)
+
+ + + + + +tinytable_l1df4fw6ykbqlfthy5uq + +
+ + + + + + + + + + + + + + + + + + +
MeanSD
Flipper length (mm)200.92 14.06
Body mass (g) 4201.75801.95
+
+ + +
+
+

However, thanks to the tables package, datasummary offers two additional mechanisms to rename. First, we can wrap a term in parentheses and use the equal = sign: (NewName=OldName):

+
+
datasummary((`Flipper length (mm)` = flipper_length_mm) + (`Body mass (g)` = body_mass_g) ~
+            island * ((Avg. = Mean) + (Std.Dev. = SD)),
+            data = penguins)
+
+ + + + + +tinytable_q562iihrzrltd3omj3wu + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BiscoeDreamTorgersen
Avg.Std.Dev.Avg.Std.Dev.Avg.Std.Dev.
Flipper length (mm)209.71 14.14 193.07 7.51 191.20 6.23
Body mass (g) 4716.02782.863712.90416.643706.37445.11
+
+ + +
+
+

Second, we can use the Heading() function:

+
+
datasummary(Heading("Flipper length (mm)") * flipper_length_mm + Heading("Body mass (g)") * body_mass_g ~ island * (Mean + SD),
+            data = penguins)
+
+ + + + + +tinytable_42kmj5amrwnqfri6id0g + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BiscoeDreamTorgersen
MeanSDMeanSDMeanSD
Flipper length (mm)209.71 14.14 193.07 7.51 191.20 6.23
Body mass (g) 4716.02782.863712.90416.643706.37445.11
+
+ + +
+
+

The Heading function also has a nearData argument which can be useful in cases where some rows are nested but others are not. Compare the last row of these two tables:

+
+
datasummary(sex * (flipper_length_mm + bill_length_mm) + Heading("Body mass (g)") * body_mass_g ~ Mean + SD,
+            data = penguins)
+
+ + + + + +tinytable_z0m6uhwkdk24qaiawiuf + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sex MeanSD
femaleflipper_length_mm197.36 12.50
bill_length_mm 42.10 4.90
male flipper_length_mm204.51 14.55
bill_length_mm 45.85 5.37
Body mass (g) 4201.75801.95
+
+ + +
+
datasummary(sex * (flipper_length_mm + bill_length_mm) + Heading("Body mass (g)", nearData=FALSE) * body_mass_g ~ Mean + SD,
+            data = penguins)
+
+ + + + + +tinytable_q1qh5myyxgetbfabh6jb + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sex MeanSD
female flipper_length_mm197.36 12.50
bill_length_mm 42.10 4.90
male flipper_length_mm204.51 14.55
bill_length_mm 45.85 5.37
Body mass (g) 4201.75801.95
+
+ + +
+
+

Counts and Percentages

+

The tables package allows datasummary to use neat tricks to produce frequency tables:

+
    +
  1. Add a N to the right-hand side of the equation.
  2. +
  3. Add Percent() to the right-hand side to calculate the percentage of observations in each cell.
  4. +
  5. Add 1 to the left-hand side to include a row with the total number of observations:
  6. +
+
+
datasummary(species * sex + 1 ~ N + Percent(),
+            data = penguins)
+
+ + + + + +tinytable_4oiqdzsiqr8226nhkgc4 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
speciessexNPercent
Adelie female73 21.22
male 73 21.22
Chinstrapfemale34 9.88
male 34 9.88
Gentoo female58 16.86
male 61 17.73
All 344100.00
+
+ + +
+
+

Note that the Percent() function accepts a denom argument to determine if percentages should be calculated row or column-wise, or if they should take into account all cells.

+

Weighted percentages

+

The Percent() pseudo-function also accepts a fn argument, which must be a function which accepts two vectors: x is the values in the current cell, and y is all the values in the whole dataset. The default fn is:

+
+
datasummary(species * sex + 1 ~ N + Percent(fn = function(x, y) 100 * length(x) / length(y)),
+            data = penguins)
+
+ + + + + +tinytable_jsa0bvkvf60q065zqe8n + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
speciessexNPercent
Adelie female73 21.22
male 73 21.22
Chinstrapfemale34 9.88
male 34 9.88
Gentoo female58 16.86
male 61 17.73
All 344100.00
+
+ + +
+
+

The code above takes the number of elements in the cell length(x) and divides it by the number of total elements length(y).

+

Now, let’s say we want to display percentages weighted by one of the variables of the dataset. This can often be useful with survey weights, for example. Here, we use an arbitrary column of weights called flipper_length_mm:

+
+
wtpct <- function(x, y) sum(x, na.rm = TRUE) / sum(y, na.rm = TRUE) * 100
+datasummary(species * sex + 1 ~ N + flipper_length_mm * Percent(fn = wtpct),
+            data = penguins)
+
+ + + + + +tinytable_ubh94hnbw1kbbhs1z17n + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
speciessexNPercent
Adelie female73 19.95
male 73 20.44
Chinstrapfemale34 9.49
male 34 9.89
Gentoo female58 17.95
male 61 19.67
All 344100.00
+
+ + +
+
+

In each cell we now have the sum of weights in that cell, divided by the total sum of weights in the column.

+

Custom percentages

+

Here is another simple illustration of Percent function mechanism in action, where we combine counts and percentages in a simple nice label:

+
+
dat <- mtcars
+dat$cyl <- as.factor(dat$cyl)
+
+fn <- function(x, y) {
+    out <- sprintf(
+        "%s (%.1f%%)",
+        length(x),
+        length(x) / length(y) * 100)
+}
+datasummary(
+    cyl ~ Percent(fn = fn),
+    data = dat)
+
+ + + + + +tinytable_ne5jddm7lnfjb8raeoh6 + +
+ + + + + + + + + + + + + + + + + + + +
cylPercent
411 (34.4%)
67 (21.9%)
814 (43.8%)
+
+ + +
+
+

Factor

+

The * nesting operator that we used above works automatically for factor, character, and logical variables. Sometimes, it is convenient to use it with other types of variables, such as binary numeric variables. In that case, we can wrap the variable name inside a call to Factor(). This allows us to treat a variable as factor, without having to modify it in the original data. For example, in the mtcars data, there is a binary numeric variable call am. We nest statistics within categories of am by typing:

+
+
datasummary(mpg + hp ~ Factor(am) * (mean + sd),
+            data = mtcars)
+
+ + + + + +tinytable_5l3c7wwc9ffk7su8j1zl + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
01
meansdmeansd
mpg17.15 3.83 24.39 6.17
hp 160.2653.91126.8584.06
+
+ + +
+
+

+Arguments: na.rm=TRUE +

+

We can pass any argument to the summary function by including a call to Arguments(). For instance, there are missing values in the flipper_length_mm variable of the penguins dataset. Therefore, the standard mean function will produce no result, because its default argument is na.rm=FALSE. We can change that by calling:

+
+
datasummary(flipper_length_mm ~ mean + mean*Arguments(na.rm=TRUE),
+            data = penguins)
+
+ + + + + +tinytable_1pr57ay39ftz1ti891i7 + +
+ + + + + + + + + + + +
meanmean
flipper_length_mm200.92
+
+ + +
+
+

Notice that there is an empty cell (NA) under the normal mean function, but that the mean call with Arguments(na.rm=TRUE) produced a numeric result.

+

We can pass the same arguments to multiple functions using the parentheses:

+
+
datasummary(flipper_length_mm ~ (mean + sd) * Arguments(na.rm=TRUE),
+            data = penguins)
+
+ + + + + +tinytable_5gl55tjokliekijsa0fp + +
+ + + + + + + + + + + +
meansd
flipper_length_mm200.9214.06
+
+ + +
+
+

Note that the shortcut functions that modelsummary supplies use na.rm=TRUE by default, so we can use them directly without arguments, even when there are missing values:

+
+
datasummary(flipper_length_mm ~ Mean + Var + P75 + Range,
+            data = penguins)
+
+ + + + + +tinytable_2crh9dfo2okr42i4yx76 + +
+ + + + + + + + + + + + + + + +
MeanVarP75Range
flipper_length_mm200.92197.73213.0059.00
+
+ + +
+
+

+Arguments: Weighted Mean

+

You can use the Arguments mechanism to do various things, such as calculating weighted means:

+
+
newdata <- data.frame(
+  x = rnorm(20),
+  w = rnorm(20),
+  y = rnorm(20))
+
+datasummary(x + y ~ weighted.mean * Arguments(w = w),
+            data = newdata)
+
+ + + + + +tinytable_5qr7gp07pfpwbhdeivhx + +
+ + + + + + + + + + + + + + + +
weighted.mean
x0.43
y-5.49
+
+ + +
+
+

Which produces the same results as:

+
+
weighted.mean(newdata$x, newdata$w)
+
+
[1] 0.4323834
+
+
weighted.mean(newdata$y, newdata$w)
+
+
[1] -5.486109
+
+
+

But different results from:

+
+
mean(newdata$x)
+
+
[1] -0.03057975
+
+
mean(newdata$y)
+
+
[1] -0.06711904
+
+
+

Logical subsets

+

Cool stuff is possible with logical subsets:

+
+
datasummary((bill_length_mm > 44.5) + (bill_length_mm <= 44.5) ~ Mean * flipper_length_mm,
+            data = penguins)
+
+ + + + + +tinytable_yci9nl094rd54beco9lu + +
+ + + + + + + + + + + + + + + +
bill_length_mm > 44.5 209.68
bill_length_mm + 192.45
+
+ + +
+
+

See the tables package documentation for more details and examples.

+

Missing values

+

At least 3 distinct issues can arise related to missing values.

+

Functions and na.rm +

+

An empty cell can appear in the table when a statistical function returns NA instead of a numeric value. In those cases, you should:

+
    +
  1. Make sure that your statistical function (e.g., mean or sd) uses na.rm=TRUE by default
  2. +
  3. Use the Arguments strategy to set na.rm=TRUE (see the Arguments section of this vignette).
  4. +
  5. Use a convenience function supplied by modelsummary, where na.rm is TRUE by default: Mean, SD, P25, etc.
  6. +

Empty crosstab cells

+

An empty cell can appear in the table when a crosstab is deeply nested, and there are no observations for a given combination of covariates. In those cases, you can use the * DropEmpty pseudo-function. See the “Empty cells” section of this vignette for examples.

+
+
datasummary(island * species * body_mass_g ~ sex * (Mean + SD),
+            data = penguins)
+
+ + + + + +tinytable_1f24cy9rgp2sbabygmu7 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
femalemale
islandspecies MeanSDMeanSD
Biscoe Adelie body_mass_g3369.32343.474050.00355.57
Chinstrapbody_mass_g
Gentoo body_mass_g4679.74281.585484.84313.16
Dream Adelie body_mass_g3344.44212.064045.54330.55
Chinstrapbody_mass_g3527.21285.333938.97362.14
Gentoo body_mass_g
TorgersenAdelie body_mass_g3395.83259.144034.78372.47
Chinstrapbody_mass_g
Gentoo body_mass_g
+
+ + +
+
datasummary(island * species * body_mass_g ~ sex * (Mean + SD) * DropEmpty(),
+            data = penguins)
+
+ + + + + +tinytable_pszc9mhzt5mv9toh1jfg + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
femalemale
islandspecies MeanSDMeanSD
Biscoe Adelie body_mass_g3369.32343.474050.00355.57
Gentoo body_mass_g4679.74281.585484.84313.16
Dream Adelie body_mass_g3344.44212.064045.54330.55
Chinstrapbody_mass_g3527.21285.333938.97362.14
TorgersenAdelie body_mass_g3395.83259.144034.78372.47
+
+ + +
+
+

Percent()

+

By default, the Percent() function computes the share of each category with respect to the whole data, including missing observations, but we can work around this with some trickery:jig

+
+
dat <- data.frame(z = c(0,0,1,0,NA,0,1))
+
+prop.table(table(dat$z))
+
+

+        0         1 
+0.6666667 0.3333333 
+
+
datasummary(Factor(z) ~ N + Percent(), data = dat)
+
+ + + + + +tinytable_u1d3e8xtavanqxwuqdqi + +
+ + + + + + + + + + + + + + + + + + +
zNPercent
0457.14
1228.57
+
+ + +
+
+

To count percentages without missing values, we can exploit the fact that Percent() accepts a denom argument which can be a logical vector:

+
+
datasummary(Factor(z) ~ N + Percent(denom = !is.na(dat$z)), data = dat)
+
+ + + + + +tinytable_x5g7lf98ftjgx3pl94n4 + +
+ + + + + + + + + + + + + + + + + + +
zNPercent
0466.67
1233.33
+
+ + +
+
+

Add rows

+
+
new_rows <- data.frame('Does',
+                       2,
+                       'plus',
+                       2,
+                       'equals',
+                       5,
+                       '?')
+datasummary(flipper_length_mm + body_mass_g ~ species * (Mean + SD),
+            data = penguins,
+            add_rows = new_rows)
+
+ + + + + +tinytable_qg03gd1kumcgoeltrowl + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AdelieChinstrapGentoo
MeanSDMeanSDMeanSD
flipper_length_mm189.95 6.54 195.82 7.13 217.19 6.48
body_mass_g 3700.66458.573733.09384.345076.02504.12
Does 2.00 plus 2.00 equals5.00 ?
+
+ + +
+
+

Add columns

+
+
new_cols <- data.frame('New Stat' = runif(2))
+datasummary(flipper_length_mm + body_mass_g ~ species * (Mean + SD),
+            data = penguins,
+            add_columns = new_cols)
+
+ + + + + +tinytable_5ul89860ntoihfccw3u6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AdelieChinstrapGentoo
MeanSDMeanSDMeanSDNew.Stat
flipper_length_mm189.95 6.54 195.82 7.13 217.19 6.48 0.52
body_mass_g 3700.66458.573733.09384.345076.02504.120.12
+
+ + +
+
+

Output formats

+

All functions in the datasummary_* family accept the same output argument. Tables can be saved to several file formats:

+
+
f <- flipper_length_mm ~ island * (mean + sd)
+datasummary(f, data = penguins, output = 'table.html')
+datasummary(f, data = penguins, output = 'table.tex')
+datasummary(f, data = penguins, output = 'table.docx')
+datasummary(f, data = penguins, output = 'table.pptx')
+datasummary(f, data = penguins, output = 'table.md')
+datasummary(f, data = penguins, output = 'table.rtf')
+datasummary(f, data = penguins, output = 'table.jpg')
+datasummary(f, data = penguins, output = 'table.png')
+
+

They can be returned in human-readable data.frames, markdown, html, or LaTeX code to the console:

+
+
datasummary(f, data = penguins, output = 'data.frame')
+datasummary(f, data = penguins, output = 'markdown')
+datasummary(f, data = penguins, output = 'html')
+datasummary(f, data = penguins, output = 'latex')
+
+

datasummary can return objects compatible with the tinytable, gt, kableExtra, flextable, huxtable, and DT table creation and customization packages:

+
+
datasummary(f, data = penguins, output = 'tinytable')
+datasummary(f, data = penguins, output = 'gt')
+datasummary(f, data = penguins, output = 'kableExtra')
+datasummary(f, data = penguins, output = 'flextable')
+datasummary(f, data = penguins, output = 'huxtable')
+datasummary(f, data = penguins, output = 'DT')
+
+

Please note that hierarchical or “nested” column labels are only available for these output formats: kableExtra, gt, html, rtf, and LaTeX. When saving tables to other formats, nested labels will be combined to a “flat” header.

+

Rounding

+

The fmt argument allows us to set the printing format of numeric values. It accepts a single number representing the number of digits after the period, or a string to be passed to the sprintf function. For instance, setting fmt="%.4f" will keep 4 digits after the dot (see ?sprintf for more options):

+
+
datasummary(flipper_length_mm ~ Mean + SD,
+            fmt = 4,
+            data = penguins)
+
+ + + + + +tinytable_qua3xn7je9hovazb5ebl + +
+ + + + + + + + + + + +
MeanSD
flipper_length_mm200.915214.0617
+
+ + +
+
+

We can set the formatting on a term-by-term basis by using the same Arguments function that we used to handle missing values in the previous section. The shortcut functions that ship with modelsummary (e.g., Mean, SD, Median, P25) all include a fmt argument:

+
+
datasummary(flipper_length_mm ~ Mean * Arguments(fmt = "%.4f") + SD * Arguments(fmt = "%.1f"),
+            data = penguins)
+
+ + + + + +tinytable_bn4gnpuq5287nzegurnk + +
+ + + + + + + + + + + +
MeanSD
flipper_length_mm200.915214.1
+
+ + +
+
+

Note that the N() function is supplied by the upstream tables package, and does not have a fmt argument. Fortunately, it is easy to override the built-in function to use custom formatting:

+
+
tmp <- data.frame(X = sample(letters[1:3], 1e6, replace = TRUE))
+N <- \(x) format(length(x), big.mark = ",")
+datasummary(X ~ N, data = tmp)
+
+ + + + + +tinytable_06ooveagghozasbh6r26 + +
+ + + + + + + + + + + + + + + + + + + +
XN
a332,683
b333,663
c333,654
+
+ + +
+
+

Titles and notes

+

datasummary includes the same title and notes arguments as in modelsummary:

+
+
datasummary(All(penguins) ~ Mean + SD,
+            data = penguins,
+            title = 'Statistics about the famous Palmer Penguins.',
+            notes = c('A note at the bottom of the table.'))
+
+ + + + + +tinytable_t946x7pc7huvbbkdvou6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Statistics about the famous Palmer Penguins.
MeanSD
A note at the bottom of the table.
rownames 172.50 99.45
bill_length_mm 43.92 5.46
bill_depth_mm 17.15 1.97
flipper_length_mm200.92 14.06
body_mass_g 4201.75801.95
year 2008.030.82
+
+ + +
+
+

Alignment

+

We can align columns using the align argument. align should be a string of length equal to the number of columns, and which includes only the letters “l”, “c”, or “r”:

+
+
datasummary(flipper_length_mm + bill_length_mm ~ Mean + SD + Range,
+            data = penguins,
+            align = 'lrcl')
+
+ + + + + +tinytable_a6ly3au3d9gpwq96da8u + +
+ + + + + + + + + + + + + + + + + + + + + +
MeanSDRange
flipper_length_mm200.9214.0659.00
bill_length_mm 43.92 5.46 27.50
+
+ + +
+
+

Factors

+

By default, the factor function in R does not assign a distinct factor level to missing values: the factor function’s exclude argument is set to NA by default. To ensure that NAs appear in your table, make sure you set exclude=NULL when you create the factor.

+

Internally, the datasummary_balance and datasummary_crosstab functions convert logical and character variables to factor with the exclude=NULL argument. This means that NAs will appear in the table as distinct rows/columns. If you do not want NAs to appear in your table, convert them to factors yourself ahead of time. For example:

+
+
mycars <- mtcars[, c("cyl", "mpg", "hp", "vs")]
+mycars$cyl[c(1, 3, 6, 8)] <- NA
+mycars$cyl_nona <- factor(mycars$cyl)
+mycars$cyl_na <- factor(mycars$cyl, exclude = NULL)
+
+datasummary_crosstab(cyl_nona ~ vs, data = mycars)
+
+ + + + + +tinytable_3389mseil3wyd15qkj3q + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cyl_nona 01All
4 N 1 8 9
% row11.1 88.9100.0
6 N 2 3 5
% row40.0 60.0100.0
8 N 14 0 14
% row100.00.0 100.0
AllN 18 14 32
% row56.2 43.8100.0
+
+ + +
+
datasummary_crosstab(cyl_na ~ vs, data = mycars)
+
+ + + + + +tinytable_6qj9j82r8orxdmh9uz8g + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cyl_na 01All
4 N 1 8 9
% row11.1 88.9100.0
6 N 2 3 5
% row40.0 60.0100.0
8 N 14 0 14
% row100.00.0 100.0
NA N 1 3 4
% row25.0 75.0100.0
AllN 18 14 32
% row56.2 43.8100.0
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/vignettes/get_started.html b/docs/vignettes/get_started.html new file mode 100644 index 000000000..2ad51a1f7 --- /dev/null +++ b/docs/vignettes/get_started.html @@ -0,0 +1,2085 @@ + + + + + + +modelsummary: Data and Model Summaries in R – Getting started + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+

Getting started

+
+ + + +
+ + + + +
+ + + +
+ +
+

To begin, load the modelsummary package and download data from the Rdatasets archive:

+
+
library(modelsummary)
+library(tinytable)
+
+url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv'
+dat <- read.csv(url) 
+dat$Small <- dat$Pop1831 > median(dat$Pop1831)
+dat <- dat[, 
+  c("Donations", "Literacy", "Commerce", "Crime_pers", "Crime_prop", "Clergy", "Small")
+]
+
+

Data Summaries

+

Quick overview of the data:

+
+ +
+
Warning: The `replace_na` argument was renamed `replace`.
+
+
+ + + + + +tinytable_qp4vhdm4xbnlhue8co0a + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UniqueMissing Pct.MeanSDMinMedianMaxHistogram
Donations8507075.55834.61246.05020.037015.0
Literacy50039.317.412.038.074.0
Commerce84042.825.01.042.586.0
Crime_pers85019754.47504.72199.018748.537014.0
Crime_prop8607843.13051.41368.07595.020235.0
Clergy85043.425.01.043.586.0
SmallN%
FALSE4350.0
TRUE4350.0
+
+ + +
+
+

Balance table (aka “Table 1”) with differences in means by subgroups:

+
+
datasummary_balance(~Small, dat)
+
+ + + + + +tinytable_4lo67dbx8d3w2zifim0h + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FALSE (N=43)TRUE (N=43)
MeanStd. Dev.MeanStd. Dev.Diff. in MeansStd. Error
Donations 7258.5 6194.16892.6 5519.0-365.9 1265.2
Literacy 37.9 19.1 40.6 15.6 2.7 3.8
Commerce 42.7 24.6 43.0 25.7 0.3 5.4
Crime_pers18040.67638.421468.27044.33427.7 1584.6
Crime_prop8422.5 3406.77263.7 2559.3-1158.8649.8
Clergy 39.1 26.7 47.7 22.7 8.6 5.3
+
+ + +
+
+

Correlation table:

+
+ +
+ + + + + +tinytable_eihf2074ydx9ewxee9ph + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DonationsLiteracyCommerceCrime_persCrime_propClergy
Donations 1 . . . . .
Literacy -.131 . . . .
Commerce .30 -.581 . . .
Crime_pers-.04-.04.05 1 . .
Crime_prop-.13-.37.41 .271 .
Clergy .09 -.17-.12.26-.071
+
+ + +
+
+

Two variables and two statistics, nested in subgroups:

+
+
datasummary(Literacy + Commerce ~ Small * (mean + sd), dat)
+
+ + + + + +tinytable_jgn2kgdkuhvx18wmu5ql + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FALSETRUE
meansdmeansd
Literacy37.8819.0840.6315.57
Commerce42.6524.5942.9525.75
+
+ + +
+
+

Model Summaries

+

Estimate a linear model and display the results:

+
+
mod <- lm(Donations ~ Crime_prop, data = dat)
+
+modelsummary(mod)
+
+ + + + + +tinytable_fi5e5k990wwpf66l5pwc + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)9065.287
(1738.926)
Crime_prop -0.254
(0.207)
Num.Obs. 86
R2 0.018
R2 Adj. 0.006
AIC 1739.0
BIC 1746.4
Log.Lik. -866.516
F 1.505
RMSE 5749.29
+
+ + +
+
+

Now estimate five regression models, display the results side-by-side, and use the group_tt() function from the tinytable package to add column labels:

+
+
library(tinytable)
+
+models <- list(
+    "I" = lm(Donations ~ Literacy + Clergy, data = dat),
+    "II" = lm(Crime_pers ~ Literacy + Clergy, data = dat),
+    "III" = lm(Crime_prop ~ Literacy + Clergy, data = dat),
+    "IV" = glm(Crime_pers ~ Literacy + Commerce, family = poisson, data = dat),
+    "V" = glm(Donations ~ Literacy + Commerce, family = poisson, data = dat)
+)
+
+modelsummary(models, stars = TRUE, gof_omit = "IC|Adj|F|RMSE|Log") |>
+    group_tt(j = list("Linear" = 2:4, "Poisson" = 5:6))
+
+ + + + + +tinytable_h0rz3rj7doax5ogrzmu6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LinearPoisson
IIIIIIIVV
+ p
(Intercept)7948.667***16259.384***11243.544***9.876***8.241***
(2078.276) (2611.140) (1011.240) (0.003) (0.006)
Literacy -39.121 3.680 -68.507*** 0.000***0.003***
(37.052) (46.552) (18.029) (0.000) (0.000)
Clergy 15.257 77.148* -16.376
(25.735) (32.334) (12.522)
Commerce 0.001***0.011***
(0.000) (0.000)
Num.Obs. 86 86 86 86 86
R2 0.020 0.065 0.152
+
+ + +
+
+

Now, save it to a Microsoft Word document:

+
+
modelsummary(models, output = "table.docx")
+
+

And draw a coefficient plot:

+
+
ols <- models[1:3]
+modelplot(ols, coef_omit = "Intercept")
+
+
+

+
+
+
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/vignettes/get_started_files/figure-html/unnamed-chunk-11-1.png b/docs/vignettes/get_started_files/figure-html/unnamed-chunk-11-1.png new file mode 100644 index 000000000..9f0ac5a06 Binary files /dev/null and b/docs/vignettes/get_started_files/figure-html/unnamed-chunk-11-1.png differ diff --git a/docs/vignettes/modelplot.html b/docs/vignettes/modelplot.html new file mode 100644 index 000000000..3903dd70f --- /dev/null +++ b/docs/vignettes/modelplot.html @@ -0,0 +1,1399 @@ + + + + + + +modelsummary: Data and Model Summaries in R – Model Plots + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+

Model Plots

+
+ + + +
+ + + + +
+ + + +
+ +
+

modelplot is a function from the modelsummary package. It allows you to plot model estimates and confidence intervals. It makes it easy to subset, rename, reorder, and customize plots using same mechanics as in modelsummary.

+

To illustrate how the function works, we fit a linear model to data about the Palmer Penguins:

+
+
url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/palmerpenguins/penguins.csv'
+dat <- read.csv(url)
+
+# rescale mm -> cm
+dat$bill_length_cm <- dat$bill_length_mm / 10
+dat$flipper_length_cm <- dat$flipper_length_mm / 10
+
+mod <- lm(bill_length_cm ~ flipper_length_cm + species, data = dat)
+
+

Then, we load the modelsummary library and call modelplot:

+
+ +
+
+

+
+
+
+
+

Rename, reorder, subset

+

modelplot uses the same mechanics as modelsummary to rename, reorder, and subset estimates. First, you can use the coef_omit argument. This will omit any coefficient that matches a string or regular expression. To omit the intercept, for example, we can type:

+
+
modelplot(mod, coef_omit = 'Interc')
+
+
+

+
+
+
+
+

Second, you can use the coef_map argument. coef_map is a named character vector, where names correspond to the original term names, and values correspond the names you want to assign. Any variable that is not included in coef_map will be excluded. Variables will also be drawn in the same order as in coef_map:

+
+
cm <- c('speciesChinstrap' = 'Chinstrap',
+        'speciesGentoo' = 'Gentoo', 
+        'flipper_length_cm' = 'Flipper length (cm)')
+
+modelplot(mod, coef_map = cm)
+
+
+

+
+
+
+
+

Several models

+

The main modelsummary functions allows you to create a table with the results of several models side-by-side, by storing them in a (potentially named) list:

+
+
models <- list(
+  "Small model" = lm(bill_length_cm ~ flipper_length_cm, data = dat),
+  "Medium model" = lm(bill_length_cm ~ flipper_length_cm + body_mass_g, data = dat),
+  "Large model" = lm(bill_length_cm ~ flipper_length_cm + body_mass_g + species, data = dat))
+
+modelsummary(models, statistic = 'conf.int')
+
+ + + + + +tinytable_xq3xgudnpnik4qr4soey + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Small modelMedium modelLarge model
(Intercept) -0.726 -0.344 0.984
[-1.356, -0.097][-1.245, 0.557][0.215, 1.752]
flipper_length_cm0.255 0.222 0.095
[0.224, 0.286] [0.158, 0.285] [0.048, 0.142]
body_mass_g 0.000 0.000
[0.000, 0.000] [0.000, 0.000]
speciesChinstrap 0.939
[0.867, 1.011]
speciesGentoo 0.207
[0.088, 0.326]
Num.Obs. 342 342 342
R2 0.431 0.433 0.817
R2 Adj. 0.429 0.430 0.815
AIC 369.0 369.6 -12.6
BIC 380.5 385.0 10.4
Log.Lik. -181.499 -180.813 12.313
F 257.092 129.365 375.333
RMSE 0.41 0.41 0.23
+
+ + +
+
+

modelplot works the same way:

+
+
modelplot(models, coef_omit = 'Interc')
+
+
+

+
+
+
+
+

Instead of displaying results with “dodged” side-by-side lines, you can also use facet:

+
+
modelplot(models, facet = TRUE)
+
+
+

+
+
+
+
+

Customizing plots

+

The graphs produced by modelplot are simple ggplot2 objects. You can thus post-process them using the normal suite of functions available for all objects of this type. Here, we change the axis labels, add a title and a caption, and use a color scheme inspired by Wes Anderson’s Darjeeling Limited:

+
+
library(wesanderson)
+library(ggplot2)
+
+modelplot(models) +
+    labs(x = 'Coefficients', 
+         y = 'Term names',
+         title = 'Linear regression models of "Bill Length (cm)"',
+         caption = "Data source: Gorman, Williams & Fraser (2014), packaged for R by @apreshill and @allison_horst") +
+    scale_color_manual(values = wes_palette('Darjeeling1'))
+
+
+

+
+
+
+
+

In ggplot2, some visual choices must be made when calling the “geom”, rather than with post-processing functions. For instance, the size, color, fatten, linetype arguments must all be specified inside the geom_pointrange function for them to take effect. modelplot will pass any unknown argument to geom_pointrange, so users can simply call:

+
+
modelplot(mod, size = 1, fatten = .7, color = 'darkgreen', linetype = 'dotted') + 
+    theme_classic()
+
+
+

+
+
+
+
+

Conditional colors and shape

+

Note: This section requires a version of modelsummary greater than 1.2.0 or the development version.

+

In a very nice Stack Overflow answer, Allan Cameron shows how we can use the aes() function from ggplot2 to add conditional aesthetics. For example, if we want to display statistically significant coefficients in a different color:

+
+
library(ggplot2)
+mod <- lm(hp ~ factor(gear) + factor(cyl), data = mtcars)
+
+modelplot(mod, coef_rename = TRUE) +
+  aes(color = ifelse(p.value < 0.001, "Significant", "Not significant")) +
+  scale_color_manual(values = c("grey", "black"))
+
+
+

+
+
+
+
+

Example: Using facets to compare models

+

Customizing plots with ggplot2 makes modelplot very flexible. For example, imagine you want to compare the coefficients of three models with different dependent variables. First, we load the packages and estimate our models:

+
+
library(ggplot2)
+library(modelsummary)
+
+models <- list(
+  lm(vs ~ carb + mpg + cyl, data = mtcars),
+  lm(disp ~ carb + mpg + cyl, data = mtcars),
+  lm(hp ~ carb + mpg + cyl, data = mtcars))
+
+

Then, we use the dvnames function to rename our list with names matching the the dependent variable in each model:

+
+
models <- dvnames(models)
+
+

By calling modelplot with the draw=FALSE argument, we see the raw data used to draw the plot. Here, we see that there is a model column:

+
+
modelplot(models, draw = FALSE)
+
+
          term model     estimate    std.error      conf.low    conf.high      p.value
+1  (Intercept)    vs   2.41742511   0.67622094    1.03224931   3.80260091 1.296718e-03
+5  (Intercept)  disp 112.57276339 114.86315481 -122.71374324 347.85927003 3.354494e-01
+9  (Intercept)    hp -10.56116383  68.75946117 -151.40853516 130.28620751 8.790301e-01
+2         carb    vs  -0.06945116   0.03943402   -0.15022810   0.01132577 8.912324e-02
+6         carb  disp -12.30144724   6.69827859  -26.02224894   1.41935446 7.692105e-02
+10        carb    hp  17.75593287   4.00972816    9.54237706  25.96948867 1.320972e-04
+3          mpg    vs  -0.01513960   0.01716410   -0.05029868   0.02001947 3.852593e-01
+7          mpg  disp  -7.14964651   2.91550156  -13.12178072  -1.17751230 2.068858e-02
+11         mpg    hp  -1.00486469   1.74527956   -4.57990780   2.57017842 5.693755e-01
+4          cyl    vs  -0.23926135   0.05687969   -0.35577411  -0.12274859 2.410214e-04
+8          cyl  disp  47.90105842   9.66160634   28.11015499  67.69196184 3.111898e-05
+12         cyl    hp  20.60581208   5.78363747    8.75856779  32.45305638 1.338485e-03
+
+
+

Finally, we use the model column as our identifier in ggplot2’s facet_grid command to display models side by side:

+
+
modelplot(models, color = "black") + facet_grid(~model)
+
+
+

+
+
+
+
+

Confidence intervals

+

You can change the \(\alpha\) level of your confidence intervals by changing the conf_level argument:

+
+
modelplot(mod, conf_level = .99)
+
+
+

+
+
+
+
modelplot(mod, conf_level = NULL)
+
+
+

+
+
+
+
+

Background annotations

+

Sometimes, you want to display annotations on a plot, but you would like to draw these annotations behind the geom_pointrange which displays the estimates. Since modelplot draws the geom_pointrange automatically, any ggplot2 annotation you add to the plot using + will be added on top of the existing ones.

+

To add your annotations in the background, you can pass them as a list of ggplot2 “geoms”:

+
+
library(ggplot2)
+
+b <- list(geom_vline(xintercept = 0, color = 'orange'),
+          annotate("rect", alpha = .1,
+                   xmin = -.5, xmax = .5, 
+                   ymin = -Inf, ymax = Inf),
+          geom_point(aes(y = term, x = estimate), alpha = .3, 
+                     size = 10, color = 'red'))
+
+modelplot(mod, background = b)
+
+
+

+
+
+
+
+

Raw data and customization

+

If you would like to customize the plots even more than what modelplot allows, you can obtain the raw data used to draw the plots by setting draw=FALSE:

+
+
modelplot(models, draw = FALSE)
+
+
          term model     estimate    std.error      conf.low    conf.high      p.value
+1  (Intercept)    vs   2.41742511   0.67622094    1.03224931   3.80260091 1.296718e-03
+5  (Intercept)  disp 112.57276339 114.86315481 -122.71374324 347.85927003 3.354494e-01
+9  (Intercept)    hp -10.56116383  68.75946117 -151.40853516 130.28620751 8.790301e-01
+2         carb    vs  -0.06945116   0.03943402   -0.15022810   0.01132577 8.912324e-02
+6         carb  disp -12.30144724   6.69827859  -26.02224894   1.41935446 7.692105e-02
+10        carb    hp  17.75593287   4.00972816    9.54237706  25.96948867 1.320972e-04
+3          mpg    vs  -0.01513960   0.01716410   -0.05029868   0.02001947 3.852593e-01
+7          mpg  disp  -7.14964651   2.91550156  -13.12178072  -1.17751230 2.068858e-02
+11         mpg    hp  -1.00486469   1.74527956   -4.57990780   2.57017842 5.693755e-01
+4          cyl    vs  -0.23926135   0.05687969   -0.35577411  -0.12274859 2.410214e-04
+8          cyl  disp  47.90105842   9.66160634   28.11015499  67.69196184 3.111898e-05
+12         cyl    hp  20.60581208   5.78363747    8.75856779  32.45305638 1.338485e-03
+
+
+

This allows users to use external tools such as the powerful ggdist package. In this example, we use the purrr::map_dfr function to call modelplot several times with different confidence levels. Then, we draw a plot where the different confidence intervals are drawn with different thicknesses:

+
+
library(tidyverse)
+library(modelsummary)
+library(ggdist)
+
+# fit
+models <- list(
+  lm(mpg ~ am, mtcars),
+  lm(mpg ~ am + cyl, mtcars))
+
+# summarize
+dat <- map_dfr(c(.8, .9, .99), function(x) {
+  modelplot(models, conf_level = x, draw = FALSE) %>%
+  mutate(.width = x)
+})
+
+# plot
+ggplot(dat, aes(
+    y = term, x = estimate,
+    xmin = conf.low, xmax = conf.high,
+    color = model)) +
+  ggdist::geom_pointinterval(
+    position = "dodge",
+    interval_size_range = c(1, 3),
+    fatten_point = .1)
+
+
+

+
+
+
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/vignettes/modelplot.pdf b/docs/vignettes/modelplot.pdf new file mode 100644 index 000000000..b935e92b3 Binary files /dev/null and b/docs/vignettes/modelplot.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-10-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-10-1.png new file mode 100644 index 000000000..0fd8f231a Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-10-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-11-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-11-1.png new file mode 100644 index 000000000..0cefc106d Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-11-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-12-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-12-1.png new file mode 100644 index 000000000..938827355 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-12-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-13-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-13-1.png new file mode 100644 index 000000000..92c234666 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-13-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-17-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-17-1.png new file mode 100644 index 000000000..c32adbc21 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-17-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-18-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-18-1.png new file mode 100644 index 000000000..0926a2082 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-18-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-18-2.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-18-2.png new file mode 100644 index 000000000..963fc6575 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-18-2.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-19-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-19-1.png new file mode 100644 index 000000000..7d0fc7b1e Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-19-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-21-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-21-1.png new file mode 100644 index 000000000..eb41d6116 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-21-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-5-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-5-1.png new file mode 100644 index 000000000..39452e412 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-5-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-6-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-6-1.png new file mode 100644 index 000000000..09f0df697 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-6-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-7-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-7-1.png new file mode 100644 index 000000000..c32ecbae2 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-7-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-9-1.png b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-9-1.png new file mode 100644 index 000000000..fb934f788 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-html/unnamed-chunk-9-1.png differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-10-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-10-1.pdf new file mode 100644 index 000000000..6b0f8eadf Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-10-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-11-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-11-1.pdf new file mode 100644 index 000000000..ca359ff6e Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-11-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-12-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-12-1.pdf new file mode 100644 index 000000000..37680571c Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-12-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-13-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-13-1.pdf new file mode 100644 index 000000000..ac83727ed Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-13-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-17-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-17-1.pdf new file mode 100644 index 000000000..a0d06e1cd Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-17-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-18-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-18-1.pdf new file mode 100644 index 000000000..42e4f4af9 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-18-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-18-2.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-18-2.pdf new file mode 100644 index 000000000..be2061501 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-18-2.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-19-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-19-1.pdf new file mode 100644 index 000000000..dac247f1c Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-19-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-21-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-21-1.pdf new file mode 100644 index 000000000..6f7d4d1e3 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-21-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-5-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-5-1.pdf new file mode 100644 index 000000000..be3d72d3c Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-5-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-6-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-6-1.pdf new file mode 100644 index 000000000..71287e71b Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-6-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-7-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-7-1.pdf new file mode 100644 index 000000000..95c7141bb Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-7-1.pdf differ diff --git a/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-9-1.pdf b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-9-1.pdf new file mode 100644 index 000000000..f7273c2a3 Binary files /dev/null and b/docs/vignettes/modelplot_files/figure-pdf/unnamed-chunk-9-1.pdf differ diff --git a/docs/vignettes/modelsummary.html b/docs/vignettes/modelsummary.html new file mode 100644 index 000000000..9594794d4 --- /dev/null +++ b/docs/vignettes/modelsummary.html @@ -0,0 +1,11523 @@ + + + + + + +modelsummary: Data and Model Summaries in R – Model Summaries + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+

Model Summaries

+
+ + + +
+ + + + +
+ + + +
+ +
+

modelsummary includes a powerful set of utilities to customize the information displayed in your model summary tables. You can easily rename, reorder, subset or omit parameter estimates; choose the set of goodness-of-fit statistics to display; display various “robust” standard errors or confidence intervals; add titles, footnotes, or source notes; insert stars or custom characters to indicate levels of statistical significance; or add rows with supplemental information about your models.

+

Before starting, we set modelsummary to use the tinytable package to draw table, and we set a few CSS properties to make tables more display in a more compact format on this website. This step is optional.

+

Now, we download data, fit some models, and summarize them in a table using the modelsummary() function:

+
+
library(modelsummary)
+
+url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv'
+dat <- read.csv(url)
+
+models <- list(
+  "OLS 1"     = lm(Donations ~ Literacy + Clergy, data = dat),
+  "Poisson" = glm(Donations ~ Literacy + Commerce, family = poisson, data = dat),
+  "OLS 2"     = lm(Crime_pers ~ Literacy + Clergy, data = dat)
+)
+
+modelsummary(models)
+
+ + + + + +tinytable_jfsnjmbp5o1ordz6e07x + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667 8.241 16259.384
(2078.276)(0.006) (2611.140)
Literacy -39.121 0.003 3.680
(37.052) (0.000) (46.552)
Clergy 15.257 77.148
(25.735) (32.334)
Commerce 0.011
(0.000)
Num.Obs. 86 86 86
R2 0.020 0.065
R2 Adj. -0.003 0.043
AIC 1740.8 274160.8 1780.0
BIC 1750.6 274168.2 1789.9
Log.Lik. -866.392 -137077.401-886.021
F 0.866 18294.559 2.903
RMSE 5740.99 5491.61 7212.97
+
+ + +
+
+

output

+

The output argument determines the type of object returned by modelsummary and/or the file where this table should be written.

+

If you want to save a table directly to file, you can type:

+
+
modelsummary(models, output = "table.docx")
+modelsummary(models, output = "table.html")
+modelsummary(models, output = "table.tex")
+modelsummary(models, output = "table.md")
+modelsummary(models, output = "table.txt")
+modelsummary(models, output = "table.png")
+
+

If you want a raw HTML, LaTeX, or Markdown table, you can type:

+
+
modelsummary(models, output = "html")
+modelsummary(models, output = "latex")
+modelsummary(models, output = "markdown")
+
+

If you to customize the appearance of your table using external tools like gt, kableExtra, flextable, or huxtable, you can type:

+
+
modelsummary(models, output = "gt")
+modelsummary(models, output = "kableExtra")
+modelsummary(models, output = "flextable")
+modelsummary(models, output = "huxtable")
+
+

Warning: When a file name is supplied to the output argument, the table is written immediately to file. If you want to customize your table by post-processing it with an external package, you need to choose a different output format and saving mechanism. The saving function differs from package to package:

+
    +
  • +tinytable: set output="tinytable", post-process your table, and use the tinytable::save_tt() function.
  • +
  • +gt: set output="gt", post-process your table, and use the gt::gtsave() function.
  • +
  • +kableExtra: set output to your destination format (e.g., “latex”, “html”, “markdown”), post-process your table, and use kableExtra::save_kable() function.
  • +
+

For example:

+
+
library(tinytable)
+modelsummary(models, output = "tinytable") |>
+  style_tt(i = 1, background = "pink") |>
+  save_tt("table.html")
+
+

fmt

+

The fmt argument defines how numeric values are rounded and presented in the table. This argument accepts three types of input:

+ +

Examples:

+
+
mod <- lm(mpg ~ hp + drat + qsec, data = mtcars)
+
+# decimal digits
+modelsummary(mod, fmt = 3)
+
+# user-supplied function
+modelsummary(mod, fmt = function(x) round(x, 2))
+
+# p values with different number of digits
+modelsummary(mod, fmt = fmt_decimal(1, 3), statistic = c("std.error", "p.value"))
+
+# significant digits
+modelsummary(mod, fmt = fmt_significant(3))
+
+# sprintf(): decimal digits
+modelsummary(mod, fmt = fmt_sprintf("%.5f"))
+
+# sprintf(): scientific notation 
+modelsummary(mod, fmt = fmt_sprintf("%.5e"))
+
+# statistic-specific formatting
+modelsummary(mod, fmt = fmt_statistic(estimate = 4, conf.int = 1), statistic = "conf.int")
+
+# term-specific formatting
+modelsummary(mod, fmt = fmt_term(hp = 4, drat = 1, default = fmt_significant(2)))
+
+modelsummary(mod, fmt = NULL)
+
+

Custom formatting function with big mark commas:

+
+
modf <- lm(I(mpg * 100) ~ hp, mtcars)
+f <- function(x) formatC(x, digits = 2, big.mark = ",", format = "f")
+modelsummary(modf, fmt = f, gof_map = NA)
+
+ + + + + +tinytable_glyrgnhixqxtuegr17l9 + +
+ + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)3,009.89
(163.39)
hp -6.82
(1.01)
+
+ + +
+
+

In many languages the comma is used as a decimal mark instead of the period. modelsummary respects the global R OutDec option, so you can simply execute this command and your tables will be adjusted automatically:

+
+
options(OutDec=",")
+
+

estimate

+

By default, modelsummary prints each coefficient estimate on its own row. You can customize this by changing the estimate argument. For example, this would produce a table of p values instead of coefficient estimates:

+
+
modelsummary(models, estimate = "p.value")
+
+

You can also use glue string, using curly braces to specify the statistics you want. For example, this displays the estimate next to a confidence interval:

+
+
modelsummary(
+  models,
+  fmt = 1,
+  estimate  = "{estimate} [{conf.low}, {conf.high}]",
+  statistic = NULL,
+  coef_omit = "Intercept")
+
+ + + + + +tinytable_am44mnfx69anbdf6b25m + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
Literacy-39.1 [-112.8, 34.6]0.0 [0.0, 0.0]3.7 [-88.9, 96.3]
Clergy 15.3 [-35.9, 66.4] 77.1 [12.8, 141.5]
Commerce 0.0 [0.0, 0.0]
Num.Obs.86 86 86
R2 0.020 0.065
R2 Adj. -0.003 0.043
AIC 1740.8 274160.8 1780.0
BIC 1750.6 274168.2 1789.9
Log.Lik.-866.392 -137077.401 -886.021
F 0.866 18294.559 2.903
RMSE 5740.99 5491.61 7212.97
+
+ + +
+
+

Glue strings can also apply R functions to estimates. However, since modelsummary rounds numbers and transforms them to character by default, we must set fmt = NULL:

+
+
m <- glm(am ~ mpg, data = mtcars, family = binomial)
+modelsummary(
+    m,
+    fmt = NULL,
+    estimate = "{round(exp(estimate), 5)}",
+    statistic = "{round(exp(estimate) * std.error, 3)}")
+
+ + + + + +tinytable_8ope661oasf7ntvkw6ja + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)0.00136
0.003
mpg 1.35938
0.156
Num.Obs. 32
AIC 33.7
BIC 36.6
Log.Lik. -14.838
F 7.148
RMSE 0.39
+
+ + +
+
+

You can also use different estimates for different models by using a vector of strings:

+
+
modelsummary(
+  models,
+  fmt = 1,
+  estimate  = c("estimate",
+                "{estimate}{stars}",
+                "{estimate} ({std.error})"),
+  statistic = NULL,
+  coef_omit = "Intercept")
+
+ + + + + +tinytable_sehg7gr8w50f6oxx7z19 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
Literacy-39.1 0.0*** 3.7 (46.6)
Clergy 15.3 77.1 (32.3)
Commerce 0.0***
Num.Obs.86 86 86
R2 0.020 0.065
R2 Adj. -0.003 0.043
AIC 1740.8 274160.8 1780.0
BIC 1750.6 274168.2 1789.9
Log.Lik.-866.392-137077.401-886.021
F 0.866 18294.559 2.903
RMSE 5740.99 5491.61 7212.97
+
+ + +
+
+

statistic

+

By default, modelsummary prints the coefficient’s standard error in parentheses below the corresponding estimate. The value of this uncertainty statistic is determined by the statistic argument. The statistic argument accepts any of the column names produced by get_estimates(model). For example:

+
+
modelsummary(models, statistic = 'std.error')
+modelsummary(models, statistic = 'p.value')
+modelsummary(models, statistic = 'statistic')
+
+

You can also display confidence intervals in brackets by setting statistic="conf.int":

+
+
modelsummary(models,
+             fmt = 1,
+             statistic = 'conf.int', 
+             conf_level = .99)
+
+ + + + + +tinytable_j7kmetgv73oamsdbj0tv + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.7 8.2 16259.4
[2469.6, 13427.8][8.2, 8.3] [9375.5, 23143.3]
Literacy -39.1 0.0 3.7
[-136.8, 58.6] [0.0, 0.0] [-119.0, 126.4]
Clergy 15.3 77.1
[-52.6, 83.1] [-8.1, 162.4]
Commerce 0.0
[0.0, 0.0]
Num.Obs. 86 86 86
R2 0.020 0.065
R2 Adj. -0.003 0.043
AIC 1740.8 274160.8 1780.0
BIC 1750.6 274168.2 1789.9
Log.Lik. -866.392 -137077.401-886.021
F 0.866 18294.559 2.903
RMSE 5740.99 5491.61 7212.97
+
+ + +
+
+

Alternatively, you can supply a glue string to get more complicated results:

+
+
modelsummary(models,
+             statistic = "{std.error} ({p.value})")
+
+ + + + + +tinytable_qx6jxd5jfg7zoilj4kbo + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667 8.241 16259.384
2078.276 ( + 0.006 ( + 2611.140 ( +
Literacy -39.121 0.003 3.680
37.052 (0.294) 0.000 ( + 46.552 (0.937)
Clergy 15.257 77.148
25.735 (0.555) 32.334 (0.019)
Commerce 0.011
0.000 ( +
Num.Obs. 86 86 86
R2 0.020 0.065
R2 Adj. -0.003 0.043
AIC 1740.8 274160.8 1780.0
BIC 1750.6 274168.2 1789.9
Log.Lik. -866.392 -137077.401 -886.021
F 0.866 18294.559 2.903
RMSE 5740.99 5491.61 7212.97
+
+ + +
+
+

You can also display several different uncertainty estimates below the coefficient estimates by using a vector. For example,

+
+
modelsummary(models, gof_omit = ".*",
+             statistic = c("conf.int",
+                           "s.e. = {std.error}", 
+                           "t = {statistic}",
+                           "p = {p.value}"))
+
+ + + + + +tinytable_56e03pmog18avcb144z6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667 8.241 16259.384
[3815.060, 12082.275][8.230, 8.252][11065.933, 21452.836]
s.e. = 2078.276 s.e. = 0.006 s.e. = 2611.140
t = 3.825 t = 1408.907 t = 6.227
p = + p = + p = +
Literacy -39.121 0.003 3.680
[-112.816, 34.574] [0.003, 0.003][-88.910, 96.270]
s.e. = 37.052 s.e. = 0.000 s.e. = 46.552
t = -1.056 t = 33.996 t = 0.079
p = 0.294 p = + p = 0.937
Clergy 15.257 77.148
[-35.930, 66.443] [12.837, 141.459]
s.e. = 25.735 s.e. = 32.334
t = 0.593 t = 2.386
p = 0.555 p = 0.019
Commerce 0.011
[0.011, 0.011]
s.e. = 0.000
t = 174.542
p = +
+
+ + +
+
+

Setting statistic=NULL omits all statistics. This can often be useful if, for example, you want to display confidence intervals next to coefficients:

+
+
modelsummary(models, gof_omit = ".*",
+             estimate = "{estimate} [{conf.low}, {conf.high}]",
+             statistic = NULL)
+
+ + + + + +tinytable_q4pkuqj17ai6iwwtw0vu + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667 [3815.060, 12082.275]8.241 [8.230, 8.252]16259.384 [11065.933, 21452.836]
Literacy -39.121 [-112.816, 34.574] 0.003 [0.003, 0.003]3.680 [-88.910, 96.270]
Clergy 15.257 [-35.930, 66.443] 77.148 [12.837, 141.459]
Commerce 0.011 [0.011, 0.011]
+
+ + +
+
+

vcov

+

You can use clustered or robust uncertainty estimates by modifying the vcov parameter. This function accepts 5 different types of input. You can use a string or a vector of strings:

+
modelsummary(models, vcov = "robust")
+modelsummary(models, vcov = c("classical", "HC3", "bootstrap"))
+

These variance-covariance matrices are calculated using the sandwich package. You can pass arguments to the sandwich functions directly from the modelsummary function. For instance, to change the number of bootstrap replicates and to specify a clustering variable we could call:

+
modelsummary(mod, vcov = "bootstrap", R = 1000, cluster = "country")
+

You can use a one-sided formula or list of one-sided formulas to use clustered standard errors:

+
modelsummary(models, vcov = ~Region)
+

You can specify a function that produces variance-covariance matrices:

+
library(sandwich)
+modelsummary(models, vcov = vcovHC)
+

You can supply a list of functions of the same length as your model list:

+
modelsummary(models, 
+  vcov = list(vcov, vcovHC, vcovHAC, vcovHC, vcov))
+

You can supply a list of named variance-covariance matrices:

+
vcov_matrices <- lapply(models, vcovHC)
+modelsummary(models, vcov = vcov_matrices)
+

You can supply a list of named vectors:

+
vc <- list(
+  `OLS 1` = c(`(Intercept)` = 2, Literacy = 3, Clergy = 4), 
+  `Poisson` = c(`(Intercept)` = 3, Literacy = -5, Commerce = 3),
+  `OLS 2` = c(`(Intercept)` = 7, Literacy = -6, Clergy = 9)
+  )
+modelsummary(models, vcov = vc)
+

stars

+

Some people like to add “stars” to their model summary tables to mark statistical significance. The stars argument can take three types of input:

+
    +
  1. +NULL omits any stars or special marks (default)
  2. +
  3. +TRUE uses these default values: + p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001 +
  4. +
  5. Named numeric vector for custom stars.
  6. +
+
modelsummary(models)
+modelsummary(models, stars = TRUE) 
+modelsummary(models, stars = c('+' = .1, '&' = .01)) 
+

Whenever stars is not NULL, modelsummary adds a note at the bottom of the table automatically. If you would like to add stars but not include a note at the bottom of the table, you can define the display of your estimate manually using a glue string, as described in the estimate argument section of the documentation. Whenever the stars string appears in the estimate or statistic arguments, modelsummary will assume that you want fine-grained control over your table, and will not include a note about stars.

+
+
modelsummary(models,
+             estimate = "{estimate}{stars}",
+             gof_omit = ".*")
+
+ + + + + +tinytable_6cvk29ov5ffg10nk7tvb + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667***8.241***16259.384***
(2078.276) (0.006) (2611.140)
Literacy -39.121 0.003***3.680
(37.052) (0.000) (46.552)
Clergy 15.257 77.148*
(25.735) (32.334)
Commerce 0.011***
(0.000)
+
+ + +
+
+

If you want to create your own stars description, you can add custom notes with the notes argument.

+

coef_omit

+

An alternative mechanism to subset coefficients is to use the coef_omit argument, which accepts a vector of integer or a regular expression. For example, we can omit the first and second coefficients as follows:

+
+
modelsummary(models, coef_omit = 1:2, gof_map = NA)
+
+ + + + + +tinytable_o7422ji70puk3t5nk5p6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
Clergy 15.257 77.148
(25.735) (32.334)
Commerce 0.011
(0.000)
+
+ + +
+
+

Negative indices determine which coefficients to keep:

+
+
modelsummary(models, coef_omit = c(-1, -2), gof_map = NA)
+
+ + + + + +tinytable_v71lspzrirwbfuz7ywcb + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667 8.241 16259.384
(2078.276)(0.006)(2611.140)
Literacy -39.121 0.003 3.680
(37.052) (0.000)(46.552)
+
+ + +
+
+

When coef_omit is a string, it is fed to grepl(x,perl=TRUE) to detect the variable names which should be excluded from the table.

+
+
modelsummary(models, coef_omit = "Intercept|.*merce", gof_map = NA)
+
+ + + + + +tinytable_kd0763zvxvccf0h65xko + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
Literacy-39.121 0.003 3.680
(37.052)(0.000)(46.552)
Clergy 15.257 77.148
(25.735) (32.334)
+
+ + +
+
+

Since coef_omit accepts regexes, you can do interesting things with it, such as specifying the list of variables that modelsummary should keep instead of omit. To do this, we use a negative lookahead. To keep only the coefficients starting with “Lit”, we call:

+
+
modelsummary(models, coef_omit = "^(?!Lit)", gof_map = NA)
+
+ + + + + +tinytable_5yv50nn8wdwn9wghwltz + +
+ + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
Literacy-39.121 0.003 3.680
(37.052)(0.000)(46.552)
+
+ + +
+
+

To keep all coefficients matching the “y” substring:

+
+
modelsummary(models, coef_omit = "^(?!.*y)", gof_map = NA)
+
+ + + + + +tinytable_b00b8uwmvzwipgbvev7a + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
Literacy-39.121 0.003 3.680
(37.052)(0.000)(46.552)
Clergy 15.257 77.148
(25.735) (32.334)
+
+ + +
+
+

To keep all coefficients matching one of two substrings:

+
+
modelsummary(models, coef_omit = "^(?!.*tercept|.*y)", gof_map = NA)
+
+ + + + + +tinytable_76yijrj7lesz4zab0bcf + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667 8.241 16259.384
(2078.276)(0.006)(2611.140)
Literacy -39.121 0.003 3.680
(37.052) (0.000)(46.552)
Clergy 15.257 77.148
(25.735) (32.334)
+
+ + +
+
+

coef_rename

+

modelsummary offers powerful and innovative mechanisms to rename, reorder, and subset coefficients and goodness-of-fit statistics.

+

You can rename coefficients using the coef_rename argument. For example, if you have two models with different explanatory variables, but you want both variables to have the same name and appear on the same row, you can do:

+
+
x <- list(lm(hp ~ drat, mtcars),
+          lm(hp ~ vs, mtcars))
+
+modelsummary(x, coef_rename = c("drat" = "Explanator", "vs" = "Explanator"))
+
+ + + + + +tinytable_8w5pw0vb25fvng1bt75x + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)353.653 189.722
(76.049)(11.347)
Explanator -57.545 -98.365
(20.922)(17.155)
Num.Obs. 32 32
R2 0.201 0.523
R2 Adj. 0.175 0.507
AIC 359.2 342.7
BIC 363.6 347.1
Log.Lik. -176.588-168.347
F 7.565 32.876
RMSE 60.31 46.61
+
+ + +
+
+

If you provide a named character vector to coef_rename, only exact matches of the complete original term name will be replaced.

+

For complex modifications, you can feed a function which returns a named vector to the coef_rename argument. For example, modelsummary ships with a function called coef_rename, which executes some common renaming tasks automatically. This example also uses the dvnames function to extract the name of the dependent variable in each model:

+
+
x <- list(
+  lm(mpg ~ factor(cyl) + drat + disp, data = mtcars),
+  lm(hp ~ factor(cyl) + drat + disp, data = mtcars)
+)
+
+modelsummary(dvnames(x), coef_rename = coef_rename)
+
+ + + + + +tinytable_szw84mb21tbvnv4s0yud + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mpghp
(Intercept)26.158 -86.788
(6.537)(79.395)
6 -4.547 46.485
(1.731)(21.027)
8 -4.580 121.892
(2.952)(35.853)
Drat 0.783 37.815
(1.478)(17.952)
Disp -0.026 0.147
(0.011)(0.137)
Num.Obs. 32 32
R2 0.786 0.756
R2 Adj. 0.754 0.720
AIC 167.4 327.2
BIC 176.2 336.0
Log.Lik. -77.719-157.623
F 24.774 20.903
RMSE 2.74 33.34
+
+ + +
+
+

Of course, you can also define your own custom functions. For instance, to rename a model with interacted variables (e.g., “drat:mpg”), you could define a custom rename_explanator function:

+
+
y <- list(
+  lm(hp ~ drat / mpg, mtcars),
+  lm(hp ~ vs / mpg, mtcars)
+)
+
+rename_explanator <- function(old_names) {
+  new_names <- gsub("drat|vs", "Explanator", old_names)
+  setNames(new_names, old_names)
+}
+
+modelsummary(y, coef_rename = rename_explanator)
+
+ + + + + +tinytable_nght3jerpohfisc4alby + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept) 91.206 189.722
(72.344)(11.205)
Explanator 68.331 -18.316
(27.390)(62.531)
Explanator:mpg-2.558 -3.260
(0.467) (2.451)
Num.Obs. 32 32
R2 0.608 0.550
R2 Adj. 0.581 0.519
AIC 338.4 342.8
BIC 344.3 348.7
Log.Lik. -165.218-167.399
F 22.454 17.743
RMSE 42.27 45.25
+
+ + +
+
+

Beware of inadvertently replacing parts of other variable names! Making your regex pattern as specific as possible (e.g., by adding word boundaries) is likely a good idea. The custom rename function is also a good place to re-introduce the replacement of “:” with “×” if you are dealing with interaction terms – modelsummary makes this replacement for you only when the coef_rename argument is not specified.

+

Another possibility is to assign variable labels to attributes in the data used to fit the model. Then, we can automatically rename them:

+
+
datlab <- mtcars
+datlab$cyl <- factor(datlab$cyl)
+attr(datlab$cyl, "label") <- "Cylinders"
+attr(datlab$am, "label") <- "Transmission"
+modlab <- lm(mpg ~ cyl + am, data = datlab)
+modelsummary(modlab, coef_rename = TRUE)
+
+ + + + + +tinytable_346yh3zlmwp1e0o6jyd0 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept) 24.802
(1.323)
Cylinders [6]-6.156
(1.536)
Cylinders [8]-10.068
(1.452)
Transmission 2.560
(1.298)
Num.Obs. 32
R2 0.765
R2 Adj. 0.740
AIC 168.4
BIC 175.7
Log.Lik. -79.199
F 30.402
RMSE 2.87
+
+ + +
+
+

coef_map

+

The coef_map argument is a named vector which allows users to rename, reorder, and subset coefficient estimates. Values of this vector correspond to the “clean” variable name. Names of this vector correspond to the “raw” variable name. The table will be sorted in the order in which terms are presented in coef_map. Coefficients which are not included in coef_map will be excluded from the table.

+
+
cm <- c('Literacy'    = 'Literacy (%)',
+        'Commerce'    = 'Patents per capita',
+        '(Intercept)' = 'Constant')
+modelsummary(models, coef_map = cm)
+
+ + + + + +tinytable_xkchgzksm7p7vgjt6quy + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
Literacy (%) -39.121 0.003 3.680
(37.052) (0.000) (46.552)
Patents per capita 0.011
(0.000)
Constant 7948.667 8.241 16259.384
(2078.276)(0.006) (2611.140)
Num.Obs. 86 86 86
R2 0.020 0.065
R2 Adj. -0.003 0.043
AIC 1740.8 274160.8 1780.0
BIC 1750.6 274168.2 1789.9
Log.Lik. -866.392 -137077.401-886.021
F 0.866 18294.559 2.903
RMSE 5740.99 5491.61 7212.97
+
+ + +
+
+

gof_omit

+

gof_omit is a regular expression which will be fed to grepl(x,perl=TRUE) to detect the names of the statistics which should be excluded from the table.

+
modelsummary(models, gof_omit = 'DF|Deviance|R2|AIC|BIC')
+

gof_map

+

The gof_map argument can be used to rename, re-order, subset, and format the statistics displayed in the bottom section of the table (“goodness-of-fit”).

+

The first type of values allowed is a character vector with elements equal to column names in the data.frame produced by get_gof(model):

+
+
modelsummary(models, gof_map = c("nobs", "r.squared"))
+
+ + + + + +tinytable_sh03za86fzwliekjaw49 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept)7948.667 8.241 16259.384
(2078.276)(0.006)(2611.140)
Literacy -39.121 0.003 3.680
(37.052) (0.000)(46.552)
Clergy 15.257 77.148
(25.735) (32.334)
Commerce 0.011
(0.000)
Num.Obs. 86 86 86
R2 0.020 0.065
+
+ + +
+
+

A more powerful mechanism is to supply a data.frame (or tibble) through the gof_map argument. This data.frame must include 3 columns:

+
    +
  1. +raw: a string with the name of a column produced by get_gof(model).
  2. +
  3. +clean: a string with the “clean” name of the statistic you want to appear in your final table.
  4. +
  5. +fmt: a string which will be used to round/format the string in question (e.g., "%.3f"). This follows the same standards as the fmt argument in ?modelsummary.
  6. +
+

You can see an example of a valid data frame by typing modelsummary::gof_map. This is the default data.frame that modelsummary uses to subset and reorder goodness-of-fit statistics. As you can see, omit == TRUE for quite a number of statistics. You can include setting omit == FALSE:

+
gm <- modelsummary::gof_map
+gm$omit <- FALSE
+modelsummary(models, gof_map = gm)
+

The goodness-of-fit statistics will be printed in the table in the same order as in the gof_map data.frame.

+
f <- function(x) format(round(x, 3), big.mark=",")
+gm <- list(
+  list("raw" = "nobs", "clean" = "N", "fmt" = f),
+  list("raw" = "AIC", "clean" = "aic", "fmt" = f))
+modelsummary(models, gof_map = gm)
+

Notice the subtle difference between coef_map and gof_map. On the one hand, coef_map works as a “white list”: any coefficient not explicitly entered will be omitted from the table. On the other, gof_map works as a “black list”: statistics need to be explicitly marked for omission.

+

Another convenient way to build a gof_map argument is to use the tribble function from the tibble package. In this example, we insert special HTML code to display a superscript, so we use the escape=FALSE argument.

+

Warning: This tribble syntax may not work well when fmt is a function. In that case, please revert to the list syntax illustrated above.

+
+
gm <- tibble::tribble(
+  ~raw,        ~clean,          ~fmt,
+  "nobs",      "N",             0,
+  "r.squared", "R<sup>2</sup>", 2)
+
+modelsummary(
+  models,
+  statistic = NULL,
+  gof_map = gm,
+  escape = FALSE)
+
+ + + + + +tinytable_82vmgjrqd00dtddk5jfa + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLS 1PoissonOLS 2
(Intercept) 7948.6678.24116259.384
Literacy -39.121 0.0033.680
Clergy 15.257 77.148
Commerce 0.011
N 86 86 86
R2 +0.02 0.07
+
+ + +
+
+

gof_function

+

The gof_function argument accepts a function which processes the model and returns a data frame with custom information about each model. For example, we can insert a row in the bottom portion of the table to display the dependent variable with:

+
+
mod <- list(
+    lm(mpg ~ qsec + drat, mtcars),
+    lm(hp ~ qsec + drat, mtcars)
+)
+
+fun <- function(model) data.frame("DV" = insight::find_response(model))
+
+modelsummary(mod, gof_function = fun)
+
+ + + + + +tinytable_rdsvrerylcolbwphlre6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)-27.840786.169
(8.299)(87.415)
qsec 1.213 -25.818
(0.402)(4.230)
drat 7.309 -49.676
(1.342)(14.138)
Num.Obs. 32 32
R2 0.592 0.650
R2 Adj. 0.564 0.626
AIC 184.1 334.7
BIC 189.9 340.6
Log.Lik. -88.026-163.371
F 21.056 26.976
RMSE 3.79 39.90
DV mpg hp
+
+ + +
+
+

In this example, we write a function factory to insert an indicator for whether a model includes control variables:

+
+
mod <- list(
+    lm(wt ~ qsec, data = mtcars),
+    lm(wt ~ qsec + hp + mpg, data = mtcars)
+)
+
+check_controls <- function(variables, yes = "✓", no = "") {
+    checkmate::assert_character(variables, min.len = 1)
+    checkmate::assert_string(no)
+    checkmate::assert_string(yes)
+    reg <- paste0("^", paste(variables, collapse = "$|^"), "$")
+    fun <- function(model) {
+        est <- get_estimates(model)
+        df <- if (all(variables %in% est$term)) yes else no
+        df <- data.frame(Controls = df)
+        return(df)
+    }
+    list("fun" = fun, "regex" = reg)
+}
+
+cc <- check_controls(c("hp", "mpg"))
+
+modelsummary(mod, 
+    gof_function = cc$fun, 
+    coef_omit = cc$regex)
+
+ + + + + +tinytable_x85j43l0ihhypdqd5h8e + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)4.925 1.290
(1.765)(1.660)
qsec -0.096 0.210
(0.098)(0.065)
Num.Obs. 32 32
R2 0.031 0.820
R2 Adj. -0.002 0.801
AIC 93.4 43.5
BIC 97.8 50.8
Log.Lik. -43.705-16.749
F 0.945 42.570
RMSE 0.95 0.41
Controls
+
+ + +
+
+

shape

+

This section requires version 1.3.1 of modelsummary. If this version is not available on CRAN yet, you can install the development version by following the instructions on the website.

+

The shape argument accepts:

+
    +
  1. A formula which determines the structure of the table, and can display “grouped” coefficients together (e.g., multivariate outcome or mixed-effects models).
  2. +
  3. The strings “cbind”, “rbind” or “rcollapse” to stack multiple tables on top of each other and present models in distinct “panels”.
  4. +
+

Formula

+

The left side of the formula represents the rows and the right side represents the columns. The default formula is term + statistic ~ model:

+
+
m <- list(
+    lm(mpg ~ hp, data = mtcars),
+    lm(mpg ~ hp + drat, data = mtcars))
+
+modelsummary(m, shape = term + statistic ~ model, gof_map = NA)
+
+ + + + + +tinytable_vnt7qobsp9k0nssieg01 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)30.099 10.790
(1.634)(5.078)
hp -0.068 -0.052
(0.010)(0.009)
drat 4.698
(1.192)
+
+ + +
+
+

We can display statistics horizontally with:

+
+
modelsummary(m,
+             shape = term ~ model + statistic,
+             statistic = "conf.int",
+             gof_map = NA)
+
+ + + + + +tinytable_rxlcffwy23qh388xn9by + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
Est.2.5 %97.5 %Est.2.5 %97.5 %
(Intercept)30.09926.76233.43610.7900.405 21.175
hp -0.068-0.089-0.048-0.052-0.071-0.033
drat 4.698 2.261 7.135
+
+ + +
+
+

The order of terms in the formula determines the order of headers in the table.

+
+
modelsummary(m,
+             shape = term ~ statistic + model,
+             statistic = "conf.int",
+             gof_map = NA)
+
+ + + + + +tinytable_qj145hvhropp2mwczza5 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Est.2.5 %97.5 %
(1)(2)(1)(2)(1)(2)
(Intercept)30.09910.79026.7620.405 33.43621.175
hp -0.068-0.052-0.089-0.071-0.048-0.033
drat 4.698 2.261 7.135
+
+ + +
+
+

shape does partial matching and will try to fill-in incomplete formulas:

+
+
modelsummary(m, shape = ~ statistic)
+
+

Some models like multinomial logit or GAMLSS produce “grouped” parameter estimates. To display these groups, we can include a group identifier in the shape formula. This group identifier must be one of the column names produced by get_estimates(model). For example, in models produced by nnet::multinom, the group identifier is called “response”:

+
+
library(nnet)
+
+dat_multinom <- mtcars
+dat_multinom$cyl <- sprintf("Cyl: %s", dat_multinom$cyl)
+
+mod <- list(
+    nnet::multinom(cyl ~ mpg, data = dat_multinom, trace = FALSE),
+    nnet::multinom(cyl ~ mpg + drat, data = dat_multinom, trace = FALSE))
+
+get_estimates(mod[[1]])
+
+
         term  estimate std.error conf.level    conf.low   conf.high statistic df.error    p.value response s.value group
+1 (Intercept) 47.252432 34.975171       0.95 -21.2976435 115.8025065  1.351028      Inf 0.17668650   Cyl: 6     2.5      
+2         mpg -2.205418  1.637963       0.95  -5.4157653   1.0049299 -1.346440      Inf 0.17816078   Cyl: 6     2.5      
+3 (Intercept) 72.440246 37.175162       0.95  -0.4217332 145.3022247  1.948619      Inf 0.05134088   Cyl: 8     4.3      
+4         mpg -3.579991  1.774693       0.95  -7.0583242  -0.1016573 -2.017246      Inf 0.04366989   Cyl: 8     4.5      
+
+
+

To summarize the results, we can type:

+
+
# modelsummary(mod, shape = term + response ~ statistic)
+
+

The terms of the shape formula above can of course be rearranged to reshape the table. For example:

+
+
modelsummary(mod, shape = model + term ~ response)
+
+ + + + + +tinytable_nlp5b6raafskihm7d3ee + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Cyl: 6Cyl: 8
(1)(Intercept)47.252 72.440
(34.975)(37.175)
mpg -2.205 -3.580
(1.638) (1.775)
(2)(Intercept)89.573 117.971
(86.884)(87.998)
mpg -3.627 -4.838
(3.869) (3.915)
drat -3.210 -5.028
(3.810) (4.199)
+
+ + +
+
+

We can combine the term and group identifier columns by inserting an interaction colon : instead of the + in the formula:

+
+
library(marginaleffects)
+mod <- glm(am ~ mpg + factor(cyl), family = binomial, data = mtcars)
+mfx <- avg_slopes(mod)
+
+modelsummary(mfx, shape = term + contrast ~ model)
+
+ + + + + +tinytable_py6wc0b5ikoyxxjj8z0f + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
cyl 6 - 40.097
(0.166)
8 - 40.093
(0.234)
mpg dY/dX0.056
(0.027)
Num.Obs. 32
AIC 37.4
BIC 43.3
Log.Lik. -14.702
F 2.236
RMSE 0.39
+
+ + +
+
+
+
modelsummary(mfx, shape = term : contrast ~ model)
+
+ + + + + +tinytable_wxzhq2dsmatv9ot2yic8 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
cyl 6 - 40.097
(0.166)
cyl 8 - 40.093
(0.234)
mpg dY/dX0.056
(0.027)
Num.Obs. 32
AIC 37.4
BIC 43.3
Log.Lik. -14.702
F 2.236
RMSE 0.39
+
+ + +
+
+

String (“rbind” or “rcollapse”): Panels of models in stacked regression tables

+

Note: The code in this section requires version 1.3.0 or the development version of modelsummary. See the website for installation instructions.

+

This section shows how to “stack/bind” multiple regression tables on top of one another, to display the results several models side-by-side and top-to-bottom. For example, imagine that we want to present 4 different models, half of which are estimated using a different outcome variable. When using modelsummary, we store models in a list. When using modelsummary with shape="rbind" or shape="rbind", we store models in a list of lists:

+
+
gm <- c("r.squared", "nobs", "rmse")
+
+panels <- list(
+  list(
+    lm(mpg ~ 1, data = mtcars),
+    lm(mpg ~ qsec, data = mtcars)
+  ),
+  list(
+    lm(hp ~ 1, data = mtcars),
+    lm(hp ~ qsec, data = mtcars)
+  )
+)
+
+modelsummary(
+  panels,
+  shape = "rbind",
+  gof_map = gm)
+
+ + + + + +tinytable_hpqh2midrcot2aknhdkc + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)20.091 -5.114
(1.065) (10.030)
qsec 1.412
(0.559)
R2 0.000 0.175
Num.Obs. 32 32
RMSE 5.93 5.39
(Intercept)146.688 631.704
(12.120)(88.700)
qsec -27.174
(4.946)
R2 0.000 0.502
Num.Obs. 32 32
RMSE 67.48 47.64
+
+ + +
+
+

Like with modelsummary(), we can can name models and panels by naming elements of our nested list:

+
+
panels <- list(
+  "Outcome: mpg" = list(
+    "(I)" = lm(mpg ~ 1, data = mtcars),
+    "(II)" = lm(mpg ~ qsec, data = mtcars)
+  ),
+  "Outcome: hp" = list(
+    "(I)" = lm(hp ~ 1, data = mtcars),
+    "(II)" = lm(hp ~ qsec, data = mtcars)
+  )
+)
+
+modelsummary(
+  panels,
+  shape = "rbind",
+  gof_map = gm)
+
+ + + + + +tinytable_cflxrrp5071asnnh716w + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(I)(II)
(Intercept)20.091 -5.114
(1.065) (10.030)
qsec 1.412
(0.559)
R2 0.000 0.175
Num.Obs. 32 32
RMSE 5.93 5.39
(Intercept)146.688 631.704
(12.120)(88.700)
qsec -27.174
(4.946)
R2 0.000 0.502
Num.Obs. 32 32
RMSE 67.48 47.64
+
+ + +
+
+

String (“cbind”): Automatic spanning column labels

+

When using the default tinytable backend, we can use a named nested list to automatically add spanning column labels to a table:

+
+
modelsummary(panels, shape = "cbind")
+
+ + + + + +tinytable_tkydpbnalpewpc5p08pp + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Outcome: mpgOutcome: hp
(I)(II)(I) (II)
(Intercept)20.091 -5.114 146.688 631.704
(1.065) (10.030)(12.120)(88.700)
qsec 1.412 -27.174
(0.559) (4.946)
Num.Obs. 32 32 32 32
R2 0.000 0.175 0.000 0.502
R2 Adj. 0.000 0.148 0.000 0.485
AIC 208.8 204.6 364.4 344.1
BIC 211.7 209.0 367.3 348.5
Log.Lik. -102.378-99.294 -180.186-169.045
F 6.377 30.190
RMSE 5.93 5.39 67.48 47.64
+
+ + +
+
+

Renaming estimates and statistics

+

When statistics are displayed in different columns, users may want control over the statistic names. To do so, we specify the estimate and statistic as named vectors:

+
+
mod <- lm(mpg ~ factor(cyl), mtcars)
+
+modelsummary(
+    mod, 
+    estimate = c("$\\hat{\\beta}$" = "estimate"),
+    statistic = c("$\\sigma_{\\hat{\\beta}}$" = "std.error"),
+    shape = term ~ model + statistic)
+
+ + + + + +tinytable_afi912fb28rzir8w63vi + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
$\hat{\beta}$$\sigma_{\hat{\beta}}$
(Intercept) 26.664 0.972
factor(cyl)6-6.921 1.558
factor(cyl)8-11.5641.299
Num.Obs. 32
R2 0.732
R2 Adj. 0.714
AIC 170.6
BIC 176.4
Log.Lik. -81.282
F 39.698
RMSE 3.07
+
+ + +
+
+

fixest

+

The fixest package offers powerful tools to estimate multiple models using a concise syntax. fixest functions are also convenient because they return named lists of models which are easy to subset and manipulate using standard R functions like grepl.

+

For example, to introduce regressors in stepwise fashion, and to estimate models on different subsets of the data, we can do:

+
+
# estimate 4 models
+library(fixest)
+mod <- feols(
+  c(hp, mpg) ~ csw(qsec, drat) | gear,
+  data = mtcars)
+
+# select models with different outcome variables
+panels <- list(
+  "Miles per gallon" = mod[grepl("mpg", names(mod))],
+  "Horsepower" = mod[grepl("hp", names(mod))]
+)
+
+modelsummary(
+  panels,
+  shape = "rcollapse",
+  gof_omit = "IC|R2")
+
+ + + + + +tinytable_d8me8o6lt8zcqu27b1qv + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
qsec 1.436 1.519
(0.594) (0.529)
drat 5.765
(2.381)
RMSE 4.03 3.67
qsec -22.175 -22.676
(12.762)(13.004)
drat -35.106
(28.509)
RMSE 40.45 39.14
Num.Obs. 32 32
Std.Errorsby: gearby: gear
FE: gear X X
+
+ + +
+
+

We can use all the typical extension systems to add information, such as the mean of the dependent variable:

+
+
glance_custom.fixest <- function(x, ...) {
+  dv <- insight::get_response(x)
+  dv <- sprintf("%.2f", mean(dv, na.rm = TRUE))
+  data.table::data.table(`Mean of DV` = dv)
+}
+
+modelsummary(
+  panels,
+  shape = "rcollapse",
+  gof_omit = "IC|R2")
+
+ + + + + +tinytable_9yjfdj9np85iv0tdscyi + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
qsec 1.436 1.519
(0.594) (0.529)
drat 5.765
(2.381)
RMSE 4.03 3.67
Mean of DV20.09 20.09
qsec -22.175 -22.676
(12.762)(13.004)
drat -35.106
(28.509)
RMSE 40.45 39.14
Mean of DV146.69 146.69
Num.Obs. 32 32
Std.Errorsby: gearby: gear
FE: gear X X
+
+ + +
+
rm("glance_custom.fixest")
+
+

align

+

By default, modelsummary will align the first column (with coefficient names) to the left, and will center the results columns. To change this default, you can use the align argument, which accepts a string of the same length as the number of columns:

+
+
modelsummary(models, align="lrrrrr")
+
+

Users who produce PDF documents using Rmarkdown or LaTeX can also align values on the decimal dot by using the character “d” in the align argument:

+
+
modelsummary(models, align="lddddd")
+
+

See ?modelsummary for a list of commands which need to appear in the LaTeX preamble to compile tables like this one.

+

notes

+

Add notes to the bottom of your table:

+
modelsummary(models, 
+   notes = list('Text of the first note.', 
+                'Text of the second note.'))
+

title

+

You can add a title to your table as follows:

+
modelsummary(models, title = 'This is a title for my table.')
+

add_rows

+

Use the add_rows argument to add rows manually to a table. For example, let’s say you estimate two models with a factor variables and you want to insert (a) an empty line to identify the category of reference, and (b) customized information at the bottom of the table:

+
+
models <- list()
+models[['OLS']] <- lm(mpg ~ factor(cyl), mtcars)
+models[['Logit']] <- glm(am ~ factor(cyl), mtcars, family = binomial)
+
+

We create a data.frame with the same number of columns as the summary table. Then, we define a “position” attribute to specify where the new rows should be inserted in the table. Finally, we pass this data.frame to the add_rows argument:

+
+
library(tibble)
+rows <- tribble(~term,          ~OLS,  ~Logit,
+                'factor(cyl)4', '-',   '-',
+                'Info',         '???', 'XYZ')
+attr(rows, 'position') <- c(3, 9)
+
+modelsummary(models, add_rows = rows)
+
+ + + + + +tinytable_ttpg83oqy2au1ohufupk + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OLSLogit
(Intercept) 26.664 0.981
(0.972)(0.677)
factor(cyl)4- -
factor(cyl)6-6.921 -1.269
(1.558)(1.021)
factor(cyl)8-11.564-2.773
(1.299)(1.021)
Num.Obs. 32 32
Info ??? XYZ
R2 0.732
R2 Adj. 0.714
AIC 170.6 39.9
BIC 176.4 44.3
Log.Lik. -81.282-16.967
F 39.698 3.691
RMSE 3.07 0.42
+
+ + +
+
+

exponentiate

+

We can exponentiate their estimates using the exponentiate argument:

+
+
mod_logit <- glm(am ~ mpg, data = mtcars, family = binomial)
+modelsummary(mod_logit, exponentiate = TRUE)
+
+ + + + + +tinytable_1l7qtgjh037gframvidx + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)0.001
(0.003)
mpg 1.359
(0.156)
Num.Obs. 32
AIC 33.7
BIC 36.6
Log.Lik. -14.838
F 7.148
RMSE 0.39
+
+ + +
+
+

We can also present exponentiated and standard models side by side by using a logical vector:

+
+
mod_logit <- list(mod_logit, mod_logit)
+modelsummary(mod_logit, exponentiate = c(TRUE, FALSE))
+
+ + + + + +tinytable_f2yply8w5cv8b29b9wim + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)0.001 -6.604
(0.003)(2.351)
mpg 1.359 0.307
(0.156)(0.115)
Num.Obs. 32 32
AIC 33.7 33.7
BIC 36.6 36.6
Log.Lik. -14.838-14.838
F 7.148 7.148
RMSE 0.39 0.39
+
+ + +
+
+

+... Additional arguments

+

All arguments passed by the user to a modelsummary function are pushed forward in two other functions:

+
    +
  1. The function which extracts model estimates. +
      +
    • By default, additional arguments are pushed forward to parameters::parameters and performance::performance. Users can also can also use a different “backend” to extract information from model objects: the broom package. By setting the modelsummary_get global option, we tell modelsummary to use the easystats/parameters packages instead of broom. With these packages, other arguments are available, such as the metrics argument. Please refer to these package’s documentation to details.
    • +
    +
  2. +
  3. The table-making functions. +
      +
    • By default, additional arguments are pushed forward to kableExtra::kbl, but users can use a different table-making function by setting the output argument to a different value such as "gt", "flextable", or "huxtable".
    • +
    • See the Appearance vignette for examples.
    • +
    +
  4. +
+

All arguments passed supported by these functions are thus automatically available directly in modelsummary, modelplot, and the datasummary family of functions.

+

Reference categories

+

When estimating models with factor regressors, R will typically omit the reference category. We can include an empty row for the reference level automatically by using the include_reference argument. This argument is supplied by the parameters package, which modelsummary uses behind the scenes to extract model estimates. We can supply it directly to modelsummary(), which will then pass the argument forward automatically:

+
+
tmp <- transform(mtcars, cyl = factor(cyl))
+mod <- lm(mpg ~ cyl, tmp)
+modelsummary(mod, include_reference = TRUE)
+
+ + + + + +tinytable_7cu0clax9cacda2whfwt + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)26.664
(0.972)
cyl4 -
cyl6 -6.921
(1.558)
cyl8 -11.564
(1.299)
Num.Obs. 32
R2 0.732
R2 Adj. 0.714
AIC 170.6
BIC 176.4
Log.Lik. -81.282
F 39.698
RMSE 3.07
+
+ + +
+
+

Standardization

+

In some cases, it is useful to standardize coefficients before reporting them. modelsummary extracts coefficients from model objects using the parameters package, and that package offers several options for standardization: https://easystats.github.io/parameters/reference/model_parameters.default.html

+

We can pass the standardize argument directly to modelsummary or modelplot, and that argument will be forwarded to parameters. For example to refit the model on standardized data and plot the results, we can do:

+
+
mod <- lm(mpg ~ hp + am, data = mtcars)
+
+modelplot(mod, standardize = "refit")
+
+
+

+
+
+
+
+

Compare to the unstandardized plot:

+
+ +
+
+

+
+
+
+
+

Math

+

We can display math in tables by enclosing math expressions in dollars signs and setting the argument escape=FALSE:

+
+
res <- lm(wt ~ mpg + drat, mtcars)
+
+modelsummary(
+  res,
+  escape = FALSE,
+  title = "Another math expression: $\\sum_{i=1}^n x^-i$",
+  coef_rename = c("mpg" = "$\\beta_1$"))
+
+ + + + + +tinytable_hpndi3khutwpzmwp6wo1 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Another math expression: $\sum_{i=1}^n x^-i$
(1)
(Intercept)7.035
(0.597)
$\beta_1$ -0.116
(0.019)
drat -0.415
(0.218)
Num.Obs. 32
R2 0.780
R2 Adj. 0.765
AIC 47.9
BIC 53.8
Log.Lik. -19.951
F 51.510
RMSE 0.45
+
+ + +
+
+

Themes and styles

+

To customize the appearance of tables, modelsummary supports six popular and extremely powerful table-making packages:

+
    +
  1. tinytable: https://vincentarelbundock.github.io/tinytable/
  2. +
  3. gt: https://gt.rstudio.com
  4. +
  5. kableExtra: http://haozhu233.github.io/kableExtra
  6. +
  7. huxtable: https://hughjonesd.github.io/huxtable/
  8. +
  9. flextable: https://davidgohel.github.io/flextable/
  10. +
  11. DT: https://rstudio.github.io/DT
  12. +
+

The “customizing the look of your tables” vignette shows examples for all 4 packages.

+

Supported models

+

modelsummary automatically supports all the models supported by the tidy function of the broom package or the parameters function of the parameters package. The list of supported models is rapidly expanding. At the moment, it covers the following model classes:

+
+ +
+
  [1] "aareg"                    "acf"                      "afex_aov"                 "AKP"                      "anova"                    "Anova.mlm"                "anova.rms"                "aov"                      "aovlist"                  "Arima"                    "averaging"                "bamlss"                   "bayesQR"                  "bcplm"                    "befa"                     "betamfx"                  "betaor"                   "betareg"                  "BFBayesFactor"            "bfsl"                     "BGGM"                     "bifeAPEs"                 "biglm"                    "binDesign"                "binWidth"                 "blavaan"                  "blrm"                     "boot"                     "bootstrap_model"          "bracl"                    "brmsfit"                  "brmultinom"               "btergm"                   "cch"                      "censReg"                  "cgam"                     "character"                "cld"                      "clm"                      "clm2"                     "clmm"                     "clmm2"                    "coeftest"                 "comparisons"              "confint.glht"             "confusionMatrix"          "coxph"                    "cpglmm"                   "crr"                      "cv.glmnet"                "data.frame"               "dbscan"                   "default"                  "deltaMethod"              "density"                  "dep.effect"               "DirichletRegModel"        "dist"                     "draws"                    "drc"                      "durbinWatsonTest"         "emm_list"                 "emmeans"                  "emmeans_summary"          "emmGrid"                  "epi.2by2"                 "ergm"                     "fa"                       "fa.ci"                    "factanal"                 "FAMD"                     "feglm"                    "felm"                     "fitdistr"                 "fixest"                   "fixest_multi"             "flac"                     "flic"                     "ftable"                   "gam"                      "Gam"                      "gamlss"                   "gamm"                     "garch"                    "geeglm"                   "ggeffects"                "glht"                     "glimML"                   "glm"                      "glmm"                     "glmmTMB"                  "glmnet"                   "glmrob"                   "glmRob"                   "glmx"                     "gmm"                      "hclust"                   "hdbscan"                  "hglm"                     "hkmeans"                  "HLfit"                    "htest"                    "hurdle"                   "hypotheses"               "irlba"                    "ivFixed"                  "ivprobit"                 "ivreg"                    "kappa"                    "kde"                      "Kendall"                  "kmeans"                   "lavaan"                   "leveneTest"               "Line"                     "Lines"                    "list"                     "lm"                       "lm_robust"                "lm.beta"                  "lme"                      "lmodel2"                  "lmrob"                    "lmRob"                    "logical"                  "logistf"                  "logitmfx"                 "logitor"                  "lqm"                      "lqmm"                     "lsmobj"                   "manova"                   "maov"                     "map"                      "marginaleffects"          "marginalmeans"            "margins"                  "maxim"                    "maxLik"                   "mblogit"                  "Mclust"                   "mcmc"                     "mcmc.list"                "MCMCglmm"                 "mcp1"                     "mcp2"                     "med1way"                  "mediate"                  "merMod"                   "merModList"               "meta_bma"                 "meta_fixed"               "meta_random"              "metaplus"                 "mfx"                      "mhurdle"                  "mipo"                     "mira"                     "mixed"                    "MixMod"                   "mixor"                    "mjoint"                   "mle"                      "mle2"                     "mlm"                      "mlogit"                   "mmrm"                     "mmrm_fit"                 "mmrm_tmb"                 "model_fit"                "model_parameters"         "muhaz"                    "multinom"                 "mvord"                    "negbin"                   "negbinirr"                "negbinmfx"                "nestedLogit"              "nlrq"                     "nls"                      "NULL"                     "numeric"                  "omega"                    "onesampb"                 "optim"                    "orcutt"                   "osrt"                     "pairwise.htest"           "pam"                      "parameters_efa"           "parameters_pca"           "PCA"                      "pgmm"                     "plm"                      "PMCMR"                    "poissonirr"               "poissonmfx"               "poLCA"                    "polr"                     "Polygon"                  "Polygons"                 "power.htest"              "prcomp"                   "predictions"              "principal"                "probitmfx"                "pvclust"                  "pyears"                   "rcorr"                    "ref.grid"                 "regsubsets"               "ridgelm"                  "rlm"                      "rlmerMod"                 "rma"                      "robtab"                   "roc"                      "rq"                       "rqs"                      "rqss"                     "sarlm"                    "Sarlm"                    "scam"                     "selection"                "sem"                      "SemiParBIV"               "slopes"                   "SpatialLinesDataFrame"    "SpatialPolygons"          "SpatialPolygonsDataFrame" "spec"                     "speedglm"                 "speedlm"                  "stanfit"                  "stanmvreg"                "stanreg"                  "summary_emm"              "summary.glht"             "summary.lm"               "summary.plm"              "summaryDefault"           "survdiff"                 "survexp"                  "survfit"                  "survreg"                  "svd"                      "svyglm"                   "svyolr"                   "svytable"                 "systemfit"                "t1way"                    "table"                    "tobit"                    "trendPMCMR"               "trimcibt"                 "ts"                       "TukeyHSD"                 "varest"                   "vgam"                     "wbgee"                    "wbm"                      "wmcpAKP"                  "xyz"                      "yuen"                     "zcpglm"                   "zerocount"                "zeroinfl"                 "zoo"                     
+
+
+

To see if a given model is supported, you can fit it, and then call this function:

+
+ +
+

If this function does not return a valid output, you can easily (really!!) add your own support. See the next section for a tutorial. If you do this, you may consider opening an issue on the Github website of the broom package: https://github.com/tidymodels/broom/issues

+

Rmarkdown, Quarto, Org-Mode

+

Rmarkdown

+

You can use modelsummary to insert tables into dynamic documents with knitr or Rmarkdown. This minimal .Rmd file can produce tables in PDF, HTML, or RTF documents:

+ +

This .Rmd file shows illustrates how to use table numbering and cross-references to produce PDF documents using bookdown:

+ +

This .Rmd file shows how to customize tables in PDF and HTML files using gt and kableExtra functions:

+

Quarto

+

Quarto is an open source publishing system built on top of Pandoc. It was designed as a “successor” to Rmarkdown, and includes useful features for technical writing, such as built-in support for cross-references. modelsummary works automatically with Quarto. This is a minimal document with cross-references which should render automatically to PDF, HTML, and more:

+
---
+format: pdf
+title: Example
+---
+
+@tbl-mtcars shows that cars with high horse power get low miles per gallon.
+
+::: {#tbl-mtcars .cell tbl-cap='Horse Powers vs. Miles per Gallon'}
+
+```{.r .cell-code}
+library(modelsummary)
+mod <- lm(mpg ~ hp, mtcars)
+modelsummary(mod)
+```
+
+::: {.cell-output-display}
+
+```{=html}
+<!DOCTYPE html> 
+<html lang="en">
+  <head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>tinytable_l1t6havsgj5f0j9ofag2</title>
+    <style>
+.table td.tinytable_css_a91ynn7ukm4oz4fnty0f, .table th.tinytable_css_a91ynn7ukm4oz4fnty0f {    border-bottom: solid 0.1em #d3d8dc; }
+.table td.tinytable_css_eh3ubb8rdnzanq420ucz, .table th.tinytable_css_eh3ubb8rdnzanq420ucz {    text-align: left; }
+.table td.tinytable_css_9isnj1g1qtz9m0xqpxjg, .table th.tinytable_css_9isnj1g1qtz9m0xqpxjg {    text-align: center; }
+.table td.tinytable_css_tfyko8sph08ohxkfufer, .table th.tinytable_css_tfyko8sph08ohxkfufer {    border-bottom: solid 0.05em black; }
+    </style>
+    <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
+    <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+    <script>
+    MathJax = {
+      tex: {
+        inlineMath: [['$', '$'], ['\\(', '\\)']]
+      },
+      svg: {
+        fontCache: 'global'
+      }
+    };
+    </script>
+  </head>
+
+  <body>
+    <div class="container">
+      <table class="table table-borderless" id="tinytable_l1t6havsgj5f0j9ofag2" style="width: auto; margin-left: auto; margin-right: auto;" data-quarto-disable-processing='true'>
+        <thead>
+        
+              <tr>
+                <th scope="col"> </th>
+                <th scope="col">(1)</th>
+              </tr>
+        </thead>
+        
+        <tbody>
+                <tr>
+                  <td>(Intercept)</td>
+                  <td>30.099 </td>
+                </tr>
+                <tr>
+                  <td>           </td>
+                  <td>(1.634)</td>
+                </tr>
+                <tr>
+                  <td>hp         </td>
+                  <td>-0.068 </td>
+                </tr>
+                <tr>
+                  <td>           </td>
+                  <td>(0.010)</td>
+                </tr>
+                <tr>
+                  <td>Num.Obs.   </td>
+                  <td>32     </td>
+                </tr>
+                <tr>
+                  <td>R2         </td>
+                  <td>0.602  </td>
+                </tr>
+                <tr>
+                  <td>R2 Adj.    </td>
+                  <td>0.589  </td>
+                </tr>
+                <tr>
+                  <td>AIC        </td>
+                  <td>181.2  </td>
+                </tr>
+                <tr>
+                  <td>BIC        </td>
+                  <td>185.6  </td>
+                </tr>
+                <tr>
+                  <td>Log.Lik.   </td>
+                  <td>-87.619</td>
+                </tr>
+                <tr>
+                  <td>F          </td>
+                  <td>45.460 </td>
+                </tr>
+                <tr>
+                  <td>RMSE       </td>
+                  <td>3.74   </td>
+                </tr>
+        </tbody>
+      </table>
+    </div>
+
+    <script>
+      function styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(i, j, css_id) {
+        var table = document.getElementById("tinytable_l1t6havsgj5f0j9ofag2");
+        table.rows[i].cells[j].classList.add(css_id);
+      }
+      function insertSpanRow(i, colspan, content) {
+        var table = document.getElementById('tinytable_l1t6havsgj5f0j9ofag2');
+        var newRow = table.insertRow(i);
+        var newCell = newRow.insertCell(0);
+        newCell.setAttribute("colspan", colspan);
+        // newCell.innerText = content;
+        // this may be unsafe, but innerText does not interpret <br>
+        newCell.innerHTML = content;
+      }
+      function spanCell_tinytable_m9ycrvyrvktrqxs7vtgw(i, j, rowspan, colspan) {
+        var table = document.getElementById("tinytable_l1t6havsgj5f0j9ofag2");
+        const targetRow = table.rows[i];
+        const targetCell = targetRow.cells[j];
+        for (let r = 0; r < rowspan; r++) {
+          // Only start deleting cells to the right for the first row (r == 0)
+          if (r === 0) {
+            // Delete cells to the right of the target cell in the first row
+            for (let c = colspan - 1; c > 0; c--) {
+              if (table.rows[i + r].cells[j + c]) {
+                table.rows[i + r].deleteCell(j + c);
+              }
+            }
+          }
+          // For rows below the first, delete starting from the target column
+          if (r > 0) {
+            for (let c = colspan - 1; c >= 0; c--) {
+              if (table.rows[i + r] && table.rows[i + r].cells[j]) {
+                table.rows[i + r].deleteCell(j);
+              }
+            }
+          }
+        }
+        // Set rowspan and colspan of the target cell
+        targetCell.rowSpan = rowspan;
+        targetCell.colSpan = colspan;
+      }
+
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 0, 'tinytable_css_a91ynn7ukm4oz4fnty0f') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 1, 'tinytable_css_a91ynn7ukm4oz4fnty0f') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(1, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(2, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(3, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(5, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(6, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(7, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(8, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(9, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(10, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(11, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(12, 0, 'tinytable_css_eh3ubb8rdnzanq420ucz') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(0, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(1, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(2, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(3, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(5, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(6, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(7, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(8, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(9, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(10, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(11, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(12, 1, 'tinytable_css_9isnj1g1qtz9m0xqpxjg') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 0, 'tinytable_css_tfyko8sph08ohxkfufer') })
+window.addEventListener('load', function () { styleCell_tinytable_m9ycrvyrvktrqxs7vtgw(4, 1, 'tinytable_css_tfyko8sph08ohxkfufer') })
+    </script>
+
+  </body>
+
+</html>
+```
+
+:::
+:::
+

Emacs Org-Mode

+

You can use modelsummary to insert tables into Emacs Org-Mode documents, which can be exported to a variety of formats, including HTML and PDF (via LaTeX). As with anything Emacs-related, there are many ways to achieve the outcomes you want. Here is one example of an Org-Mode document which can automatically export tables to HTML and PDF without manual tweaks:

+
#+PROPERTY: header-args:R :var orgbackend=(prin1-to-string org-export-current-backend)
+#+MACRO: Rtable (eval (concat "#+header: :results output " (prin1-to-string org-export-current-backend)))
+
+{{{Rtable}}}
+#+BEGIN_SRC R :exports both
+library(modelsummary)
+options(modelsummary_factory_default = orgbackend)
+
+mod = lm(hp ~ mpg, data = mtcars)
+
+modelsummary(mod)
+#+END_SRC
+

The first line tells Org-mode to assign a variable called orgbackend. This variable will be accessible by the R session, and will be equal to “html” or “latex”, depending on the export format.

+

The second line creates an Org macro which we will use to automatically add useful information to the header of source blocks. For instance, when we export to HTML, the macro will expand to :results output html. This tells Org-Mode to insert the last printed output from the R session, and to treat it as raw HTML.

+

The {{Rtable}} call expands the macro to add information to the header of the block that follows.

+

#+BEGIN_SRC R :exports both says that we want to print both the original code and the output (:exports results would omit the code, for example).

+

Finally, options(modelsummary_factory_default=orgbackend uses the variable we defined to set the default output format. That way, we don’t have to use the output argument every time.

+

One potentially issue to keep in mind is that the code above extracts the printout from the R console. However, when we customize tables with kableExtra or gt functions, those functions do not always return printed raw HTML or LaTeX code. Sometimes, it can be necessary to add a call to cat at the end of a table customization pipeline. For example:

+
{{{Rtable}}}
+#+BEGIN_SRC R :exports both
+library(modelsummary)
+library(kableExtra)
+
+mod = lm(hp ~ mpg, data = mtcars)
+
+modelsummary(mod, output = orgbackend) %>%
+  row_spec(1, background = "pink") %>%
+  cat()
+#+END_SRC
+

Global options

+

Users can change the default behavior of modelsummary by setting global options.

+

Omit the note at the bottom of the table with significance threshold:

+
+
options("modelsummary_stars_note" = FALSE)
+
+

Change the default output format:

+
+
options(modelsummary_factory_default = "latex")
+options(modelsummary_factory_default = "gt")
+
+

Change the backend packages that modelsummary uses to create tables in different output formats:

+
+
options(modelsummary_factory_html = 'kableExtra')
+options(modelsummary_factory_latex = 'flextable')
+options(modelsummary_factory_word = 'huxtable')
+options(modelsummary_factory_png = 'gt')
+
+

Change the packages that modelsummary uses to extract information from models:

+
+
# tidymodels: broom 
+options(modelsummary_get = "broom")
+
+# easystats: performance + parameters
+options(modelsummary_get = "easystats")
+
+

The appearance vignette shows how to set “themes” for your tables using the modelsummary_theme_gt, modelsummary_theme_kableExtra, modelsummary_theme_flextable and modelsummary_theme_huxtable global options. For example:

+
+
library(gt)
+
+# The ... ellipsis is required!
+custom_theme <- function(x, ...) {
+    x %>% gt::opt_row_striping(row_striping = TRUE)
+}
+options("modelsummary_theme_gt" = custom_theme)
+
+mod <- lm(mpg ~ hp + drat, mtcars)
+modelsummary(mod, output = "gt")
+
+

Case studies

+

Collapse control variables into an indicator

+

In some cases, analysts want to display a single checkmark in their table if a full set of control variables is available. This can easily be achieved with the glance_custom mechanism described in detail in the extension vignette. Here is a simple example:

+
+
library(modelsummary)
+
+mod <- list(
+  glm(am ~ hp + factor(cyl), data = mtcars, family = binomial),
+  lm(mpg ~ hp + factor(cyl) + gear + qsec, data = mtcars)
+)
+
+glance_custom.lm <- function(x, ...) {
+  controls <- c("gear", "qsec")
+  if (all(controls %in% names(coef(x)))) {
+    out <- data.frame(Controls = "✓")
+  } else {
+    out <- data.frame(Controls = "✗")
+  }
+  return(out)
+}
+
+glance_custom.glm <- glance_custom.lm
+
+modelsummary(mod, "html", coef_omit = "qsec|gear")
+
+ + + + + +tinytable_ws4114bfqtedd4xsgc6z + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept) −2.029 33.178
(1.604)(13.713)
hp 0.038 −0.057
(0.019)(0.018)
factor(cyl)6−2.874 −4.818
(1.360)(1.805)
factor(cyl)8−8.644 −4.037
(3.423)(3.585)
Num.Obs. 32 32
R2 0.812
R2 Adj. 0.776
AIC 35.2 165.2
BIC 41.1 175.5
Log.Lik. −13.602−75.598
F 2.514 22.526
RMSE 0.38 2.57
Controls
+
+ + +
+
+

Return to nomal:

+
+
rm(list = c("glance_custom.glm", "glance_custom.lm"))
+
+

Subgroup estimation with nest_by +

+

Sometimes, it is useful to estimate multiple regression models on subsets of the data. To do this efficiently, we can use the nest_by function from the dplyr package. Then, estimate the models with lm, extract them and name them with pull, and finally summarize them with modelsummary:

+
+
library(tidyverse)
+
+mtcars %>%
+    nest_by(cyl) %>%
+    mutate(models = list(lm(mpg ~ hp, data))) %>%
+    pull(models, name = cyl) %>%
+    modelsummary
+
+ + + + + +tinytable_w4yvlonh9rkvo0nj674f + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
468
(Intercept)35.983 20.674 18.080
(5.201)(3.304)(2.988)
hp -0.113 -0.008 -0.014
(0.061)(0.027)(0.014)
Num.Obs. 11 7 14
R2 0.274 0.016 0.080
R2 Adj. 0.193 -0.181 0.004
AIC 65.8 29.9 69.8
BIC 67.0 29.7 71.8
Log.Lik. -29.891-11.954-31.920
RMSE 3.66 1.33 2.37
+
+ + +
+
+

Bootstrap

+

Users often want to use estimates or standard errors that have been obtained using a custom strategy. To achieve this in an automated and replicable way, it can be useful to use the tidy_custom strategy described above in the “Cutomizing Existing Models” section.

+

For example, we can use the modelr package to draw 500 resamples of a dataset, and compute bootstrap standard errors by taking the standard deviation of estimates computed in all of those resampled datasets. To do this, we defined tidy_custom.lm function that will automatically bootstrap any lm model supplied to modelsummary, and replace the values in the table automatically.

+

Note that the tidy_custom_lm returns a data.frame with 3 columns: term, estimate, and std.error:

+
+
library("broom")
+library("tidyverse")
+library("modelr")
+
+tidy_custom.lm <- function(x, ...) {
+  # extract data from the model
+  model.frame(x) %>%
+    # draw 500 bootstrap resamples
+    modelr::bootstrap(n = 500) %>%
+    # estimate the model 500 times
+    mutate(results = map(strap, ~ update(x, data = .))) %>%
+    # extract results using `broom::tidy`
+    mutate(results = map(results, tidy)) %>%
+    # unnest and summarize
+    unnest(results) %>%
+    group_by(term) %>%
+    summarize(std.error = sd(estimate),
+              estimate = mean(estimate))
+}
+
+mod = list(
+  lm(hp ~ mpg, mtcars) ,
+  lm(hp ~ mpg + drat, mtcars))
+
+modelsummary(mod)
+
+ + + + + +tinytable_dhfo3oc3ab7j90rherha + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)327.375 283.415
(31.272)(46.284)
mpg -9.019 -10.036
(1.442) (2.301)
drat 17.680
(21.958)
Num.Obs. 32 32
R2 0.602 0.614
R2 Adj. 0.589 0.588
AIC 336.9 337.9
BIC 341.3 343.7
Log.Lik. -165.428-164.940
F 45.460 23.100
RMSE 42.55 41.91
+
+ + +
+
+

+fixest: Fixed effects and instrumental variable regression

+

One common use-case for glance_custom is to include additional goodness-of-fit statistics. For example, in an instrumental variable estimation computed by the fixest package, we may want to include an IV-Wald statistic for the first-stage regression of each endogenous regressor:

+
+
library(fixest)
+library(tidyverse)
+
+# create a toy dataset
+base <- iris
+names(base) <- c("y", "x1", "x_endo_1", "x_inst_1", "fe")
+base$x_inst_2 <- 0.2 * base$y + 0.2 * base$x_endo_1 + rnorm(150, sd = 0.5)
+base$x_endo_2 <- 0.2 * base$y - 0.2 * base$x_inst_1 + rnorm(150, sd = 0.5)
+
+# estimate an instrumental variable model
+mod <- feols(y ~ x1 | fe | x_endo_1 + x_endo_2 ~ x_inst_1 + x_inst_2, base)
+
+# custom extractor function returns a one-row data.frame (or tibble)
+glance_custom.fixest <- function(x) {
+  tibble(
+    "Wald (x_endo_1)" = fitstat(x, "ivwald")[[1]]$stat,
+    "Wald (x_endo_2)" = fitstat(x, "ivwald")[[2]]$stat
+  )
+}
+
+# draw table
+modelsummary(mod)
+
+ + + + + +tinytable_ijejn7mhkwpr9dsmkson + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
fit_x_endo_1 2.388
(26.738)
fit_x_endo_2 20.854
(317.291)
x1 1.398
(16.551)
Num.Obs. 150
R2 -188.225
R2 Adj. -194.795
R2 Within -495.270
R2 Within Adj. -505.609
AIC 1166.5
BIC 1184.6
RMSE 11.35
Std.Errors by: fe
FE: fe X
Wald (x_endo_1)42.2275700153234
Wald (x_endo_2)0.0911469615478482
+
+ + +
+
+
+
rm("glance_custom.fixest")
+
+

Multiple imputation

+

modelsummary can pool and display analyses on several datasets imputed using the mice or Amelia packages. This code illustrates how:

+
+
library(mice)
+library(Amelia)
+
+# Download data from `Rdatasets`
+url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv'
+dat <- read.csv(url)[, c('Clergy', 'Commerce', 'Literacy')]
+
+# Insert missing values
+dat$Clergy[sample(1:nrow(dat), 10)] <- NA
+dat$Commerce[sample(1:nrow(dat), 10)] <- NA
+dat$Literacy[sample(1:nrow(dat), 10)] <- NA
+
+# Impute with `mice` and `Amelia`
+dat_mice <- mice(dat, m = 5, printFlag = FALSE)
+dat_amelia <- amelia(dat, m = 5, p2s = 0)$imputations
+
+# Estimate models
+mod <- list()
+mod[['Listwise deletion']] <- lm(Clergy ~ Literacy + Commerce, dat)
+mod[['Mice']] <- with(dat_mice, lm(Clergy ~ Literacy + Commerce)) 
+mod[['Amelia']] <- lapply(dat_amelia, function(x) lm(Clergy ~ Literacy + Commerce, x))
+
+# Pool results
+mod[['Mice']] <- mice::pool(mod[['Mice']])
+mod[['Amelia']] <- mice::pool(mod[['Amelia']])
+
+# Summarize
+modelsummary(mod)
+
+ + + + + +tinytable_ybkahyi00wojw7ksrmch + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Listwise deletionMiceAmelia
(Intercept)84.971 78.743 76.645
(14.073)(12.630)(13.559)
Literacy -0.565 -0.487 -0.476
(0.224) (0.203) (0.199)
Commerce -0.423 -0.387 -0.352
(0.162) (0.133) (0.153)
Num.Obs. 60 86 86
Num.Imp. 5 5
R2 0.131 0.118 0.098
R2 Adj. 0.101 0.096 0.076
AIC 559.8
BIC 568.2
Log.Lik. -275.909
RMSE 24.04
+
+ + +
+
+

FAQ

+

Stack Overflow is useful

+

Where can I get help?

+

First, please read the documentation in ?modelsummary and on the modelsummary website. The website includes dozens of worked examples and a lot of detailed explanation.

+

Second, try to use the [modelsummary] tag on StackOverflow.

+

Third, if you think you found a bug or have a feature request, please file it on the Github issue tracker:

+

How can I add or modify statistics in a table?

+

See the detailed documentation in the “Adding and Customizing Models” section of the modelsummary website.

+

How does modelsummary extract estimates and goodness-of-fit statistics?

+

A modelsummary table is divided in two parts: “Estimates” (top of the table) and “Goodness-of-fit” (bottom of the table). To populate those two parts, modelsummary tries using the broom, parameters and performance packages in sequence.

+

Estimates:

+
    +
  1. Try the broom::tidy function to see if that package supports this model type, or if the user defined a custom tidy function in their global environment. If this fails…
  2. +
  3. Try the parameters::model_parameters function to see if the parameters package supports this model type.
  4. +
+

Goodness-of-fit:

+
    +
  1. Try the performance::model_performance function to see if the performance package supports this model type.
  2. +
  3. Try the broom::glance function to see if that package supports this model type, or if the user defined a custom glance function in their global environment. If this fails…
  4. +
+

You can change the order in which those steps are executed by setting a global option:

+
+
# tidymodels: broom 
+options(modelsummary_get = "broom")
+
+# easystats: performance + parameters
+options(modelsummary_get = "easystats")
+
+

If all of this fails, modelsummary will return an error message.

+

If you have problems with a model object, you can often diagnose the problem by running the following commands from a clean R session:

+
# see if parameters and performance support your model type
+library(parameters)
+library(performance)
+model_parameters(model)
+model_performance(model)
+
+# see if broom supports your model type
+library(broom)
+tidy(model)
+glance(model)
+
+# see if broom.mixed supports your model type
+library(broom.mixed)
+tidy(model)
+glance(model)
+

If none of these options work, you can create your own tidy and glance methods, as described in the Adding new models section.

+

If one of the extractor functions does not work well or takes too long to process, you can define a new “custom” model class and choose your own extractors, as described in the Adding new models section.

+

How can I speed up modelsummary?

+

The modelsummary function, by itself, is not slow: it should only take a couple seconds to produce a table in any output format. However, sometimes it can be computationally expensive (and long) to extract estimates and to compute goodness-of-fit statistics for your model.

+

The main options to speed up modelsummary are:

+
    +
  1. Set gof_map=NA to avoid computing expensive goodness-of-fit statistics.
  2. +
  3. Use the easystats extractor functions and the metrics argument to avoid computing expensive statistics (see below for an example).
  4. +
  5. Use parallel computation if you are summarizing multiple models. See the “Parallel computation” section in the ?modelsummary documentation.
  6. +
+

To diagnose the slowdown and find the bottleneck, you can try to benchmark the various extractor functions:

+
+
library(tictoc)
+
+data(trade)
+mod <- lm(mpg ~ hp + drat, mtcars)
+
+tic("tidy")
+x <- broom::tidy(mod)
+toc()
+
+
tidy: 0.006 sec elapsed
+
+
tic("glance")
+x <- broom::glance(mod)
+toc()
+
+
glance: 0.01 sec elapsed
+
+
tic("parameters")
+x <- parameters::parameters(mod)
+toc()
+
+
parameters: 0.038 sec elapsed
+
+
tic("performance")
+x <- performance::performance(mod)
+toc()
+
+
performance: 0.016 sec elapsed
+
+
+

In my experience, the main bottleneck tends to be computing goodness-of-fit statistics. The performance extractor allows users to specify a metrics argument to select a subset of GOF to include. Using this can speedup things considerably.

+

We call modelsummary with the metrics argument:

+
+
modelsummary(mod, metrics = "rmse")
+
+ + + + + +tinytable_qw56knvavu3hbunozv92 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)10.790
(5.078)
hp -0.052
(0.009)
drat 4.698
(1.192)
Num.Obs. 32
R2 0.741
R2 Adj. 0.723
AIC 169.5
BIC 175.4
Log.Lik. -80.752
F 41.522
+
+ + +
+
+

Escaped LaTeX characters

+

Sometimes, users want to include raw LaTeX commands in their tables, such as coefficient names including math mode: Apple $\times$ Orange. The result of these attempts is often a weird string such as: \$\textbackslash{}times\$ instead of proper LaTeX-rendered characters.

+

The source of the problem is that kableExtra, default table-making package in modelsummary, automatically escapes weird characters to make sure that your tables compile properly in LaTeX. To avoid this, we need to pass the escape=FALSE to modelsummary:

+
+
modelsummary(mod, escape = FALSE)
+
+

Bayesian models

+

Many bayesian models are supported out-of-the-box, including those produced by the rstanarm and brms packages. The statistics available for bayesian models are slightly different than those available for most frequentist models. Users can call get_estimates to see what is available:

+
+ +
+
This is rstanarm version 2.32.1
+
+
+
- See https://mc-stan.org/rstanarm/articles/priors for changes to default priors!
+
+
+
- Default priors may change, so it's safest to specify priors, even if equivalent to the defaults.
+
+
+
- For execution on a local, multicore CPU with excess RAM we recommend calling
+
+
+
  options(mc.cores = parallel::detectCores())
+
+
+

+Attaching package: 'rstanarm'
+
+
+
The following object is masked from 'package:fixest':
+
+    se
+
+
mod <- stan_glm(am ~ hp + drat, data = mtcars)
+
+
+ +
+
         term      estimate         mad conf.level     conf.low    conf.high prior.distribution prior.location prior.scale group std.error statistic p.value
+1 (Intercept) -2.2236089637 0.589441345       0.95 -3.436529813 -1.041750262             normal        0.40625  1.24747729              NA        NA      NA
+2          hp  0.0007253039 0.001020979       0.95 -0.001507643  0.002869693             normal        0.00000  0.01819465              NA        NA      NA
+3        drat  0.7030393239 0.140505922       0.95  0.421813308  0.982043203             normal        0.00000  2.33313429              NA        NA      NA
+
+
+

This shows that there is no std.error column, but that there is a mad statistic (mean absolute deviation). So we can do:

+
+
modelsummary(mod, statistic = "mad")
+
+
Warning: 
+`modelsummary` uses the `performance` package to extract goodness-of-fit
+statistics from models of this class. You can specify the statistics you wish
+to compute by supplying a `metrics` argument to `modelsummary`, which will then
+push it forward to `performance`. Acceptable values are: "all", "common",
+"none", or a character vector of metrics names. For example: `modelsummary(mod,
+metrics = c("RMSE", "R2")` Note that some metrics are computationally
+expensive. See `?performance::performance` for details.
+ This warning appears once per session.
+
+
+ + + + + +tinytable_srx0i5lzhxrae2lelvc6 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)-2.224
(0.589)
hp 0.001
(0.001)
drat 0.703
(0.141)
Num.Obs. 32
R2 0.498
R2 Adj. 0.440
Log.Lik. -12.047
ELPD -15.0
ELPD s.e. 3.1
LOOIC 30.1
LOOIC s.e. 6.2
WAIC 29.8
RMSE 0.34
+
+ + +
+
+

As noted in the modelsummary() documentation, model results are extracted using the parameters package. Users can pass additional arguments to modelsummary(), which will then push forward those arguments to the parameters::parameters function to change the results. For example, the parameters documentation for bayesian models shows that there is a centrality argument, which allows users to report the mean and standard deviation of the posterior distribution, instead of the median and MAD:

+
+
get_estimates(mod, centrality = "mean")
+
+
         term      estimate    std.dev conf.level     conf.low    conf.high prior.distribution prior.location prior.scale group std.error statistic p.value
+1 (Intercept) -2.2221087678 0.60877621       0.95 -3.436529813 -1.041750262             normal        0.40625  1.24747729              NA        NA      NA
+2          hp  0.0007113946 0.00107747       0.95 -0.001507643  0.002869693             normal        0.00000  0.01819465              NA        NA      NA
+3        drat  0.7020620279 0.14233319       0.95  0.421813308  0.982043203             normal        0.00000  2.33313429              NA        NA      NA
+
+
modelsummary(mod, statistic = "std.dev", centrality = "mean")
+
+ + + + + +tinytable_k132niqpac5dwttdshxq + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)-2.222
(0.609)
hp 0.001
(0.001)
drat 0.702
(0.142)
Num.Obs. 32
R2 0.498
R2 Adj. 0.440
Log.Lik. -12.047
ELPD -15.0
ELPD s.e. 3.1
LOOIC 30.1
LOOIC s.e. 6.2
WAIC 29.8
RMSE 0.34
+
+ + +
+
+

We can also get additional test statistics using the test argument:

+
+
get_estimates(mod, test = c("pd", "rope"))
+
+
         term      estimate         mad conf.level     conf.low    conf.high      pd rope.percentage prior.distribution prior.location prior.scale group std.error statistic p.value
+1 (Intercept) -2.2236089637 0.589441345       0.95 -3.436529813 -1.041750262 0.99925               0             normal        0.40625  1.24747729              NA        NA      NA
+2          hp  0.0007253039 0.001020979       0.95 -0.001507643  0.002869693 0.75550               1             normal        0.00000  0.01819465              NA        NA      NA
+3        drat  0.7030393239 0.140505922       0.95  0.421813308  0.982043203 1.00000               0             normal        0.00000  2.33313429              NA        NA      NA
+
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/vignettes/modelsummary_extension.html b/docs/vignettes/modelsummary_extension.html new file mode 100644 index 000000000..6db480fc3 --- /dev/null +++ b/docs/vignettes/modelsummary_extension.html @@ -0,0 +1,1861 @@ + + + + + + +modelsummary: Data and Model Summaries in R – Extension and Customization + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+

Extension and Customization

+
+ + + +
+ + + + +
+ + + +
+ +
+ +

Unsupported models: modelsummary_list +

+

The simplest way to summarize an unsupported model is to create a modelsummary_list object. This approach is super flexible, but it requires manual intervention, and it can become tedious if you need to summarize many models. The next section shows how to add formal support for an unsupported model type.

+

A modelsummary_list is a list with two element that conform to the broom package specification: tidy and glance. tidy is a data.frame with at least three columns: term, estimate, and std.error. glance is a data.frame with only a single row, and where each column will be displayed at the bottom of the table in the goodness-of-fit section. Finally, we wrap those two elements in a list and assign it a modelsummary_list class:

+
+
ti <- data.frame(
+  term = c("coef1", "coef2", "coef3"),
+  estimate = 1:3,
+  std.error = c(pi, exp(1), sqrt(2)))
+
+gl <- data.frame(
+  stat1 = "blah",
+  stat2 = "blah blah")
+
+mod <- list(
+  tidy = ti,
+  glance = gl)
+class(mod) <- "modelsummary_list"
+
+modelsummary(mod)
+
+ + + + + +tinytable_j3rpxlg4dt6svij5pz34 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
coef11.000
(3.142)
coef22.000
(2.718)
coef33.000
(1.414)
stat1blah
stat2blah blah
+
+ + +
+
+

Unsupported models: glance and tidy +

+

modelsummary relies on two functions from the broom package to extract model information: tidy and glance. If broom doesn’t support the type of model you are trying to summarize, modelsummary won’t support it out of the box. Thankfully, it is extremely easy to add support for most models using custom methods.

+

For example, models produced by the MCMCglmm package are not currently supported by broom. To add support, you simply need to create a tidy and a glance method:

+
# load packages and data
+library(modelsummary)
+library(MCMCglmm)
+data(PlodiaPO)
+
+# add custom functions to extract estimates (tidy) and goodness-of-fit (glance) information
+tidy.MCMCglmm <- function(x, ...) {
+    s <- summary(x, ...)
+    ret <- data.frame(
+      term      = row.names(s$solutions),
+      estimate  = s$solutions[, 1],
+      conf.low  = s$solutions[, 2],
+      conf.high = s$solutions[, 3])
+    ret
+}
+
+glance.MCMCglmm <- function(x, ...) {
+    ret <- data.frame(
+      dic = x$DIC,
+      n   = nrow(x$X))
+    ret
+}
+
+# estimate a simple model
+model <- MCMCglmm(PO ~ 1 + plate, random = ~ FSfamily, data = PlodiaPO, verbose=FALSE, pr=TRUE)
+
+# summarize the model
+modelsummary(model, statistic = 'conf.int')
+

Three important things to note.

+

First, the methods are named tidy.MCMCglmm and glance.MCMCglmm because the model object I am trying to summarize is of class MCMCglmm. You can find the class of a model by running: class(model).

+

Second, both of the methods include the ellipsis ... argument.

+

Third, in the example above we used the statistic = 'conf.int' argument. This is because the tidy method produces conf.low and conf.high columns. In most cases, users will define std.error column in their custom tidy methods, so the statistic argument will need to be adjusted.

+

If you create new tidy and glance methods, please consider contributing them to broom so that the rest of the community can benefit from your work: https://github.com/tidymodels/broom

+

Modifying information: tidy_custom and glance_custom +

+

Users may want to include more information than is made available by the default extractor function. For example, models produced by the MASS::polr do not produce p values by default, which means that we cannot use the stars=TRUE argument in modelsummary. However, it is possible to extract this information by using the lmtest::coeftest function. To include such custom information, we will define new glance_custom and tidy_custom methods.

+

We begin by estimating a model with the MASS::polr:

+
+
library(MASS)
+
+mod_ordinal <- polr(as.ordered(gear) ~ mpg + drat, data = mtcars)
+
+get_estimates(mod_ordinal)
+
+
  term     estimate  std.error conf.level   conf.low  conf.high   statistic df.error      p.value component s.value group
+1  3|4 13.962948761 4.04107300       0.95  5.6851860 22.2407116  3.45525774       28 0.0017706303     alpha     9.1      
+2  4|5 16.898937342 4.39497069       0.95  7.8962480 25.9016267  3.84506258       28 0.0006356348     alpha    10.6      
+3  mpg -0.008646682 0.09034201       0.95 -0.1916706  0.1708667 -0.09571053       28 0.9244322098      beta     0.1      
+4 drat  3.949431923 1.30665144       0.95  1.6191505  6.8457246  3.02255965       28 0.0053120619      beta     7.6      
+
+
+

The get_estimates function shows that our default extractor does not produce a p.value column. As a result, setting stars=TRUE in modelsummary will produce an error.

+

We know that the MASS::polr produces an object of class polr:

+
+
class(mod_ordinal)
+
+
[1] "polr"
+
+
+

To extract more (custom) information from a model of this class, we thus define a method called tidy_custom.polr which returns a data.frame with two columns: term and p.value:

+
+
tidy_custom.polr <- function(x, ...) {
+  s <- lmtest::coeftest(x)
+  out <- data.frame(
+    term = row.names(s),
+    p.value = s[, "Pr(>|t|)"])
+  out
+}
+
+

When this method is defined, modelsummary can automatically extract p values from all models of this class, and will now work properly with stars=TRUE:

+
+
modelsummary(mod_ordinal, stars = TRUE)
+
+ + + + + +tinytable_nkgbay6upgof104ksq19 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
+ p
3|4 13.963**
(4.041)
4|5 16.899***
(4.395)
mpg -0.009
(0.090)
drat 3.949**
(1.307)
Num.Obs.32
AIC 51.1
BIC 57.0
RMSE 3.44
+
+ + +
+
+

New information: tidy_custom and glance_custom +

+

Sometimes users will want to include information that is not supplied by those functions. A pretty easy way to include extra information is to define new glance_custom and tidy_custom methods. To illustrate, we estimate two linear regression models using the lm function:

+
+
library(modelsummary)
+
+mod <- list()
+mod[[1]] <- lm(hp ~ mpg + drat, mtcars)
+mod[[2]] <- lm(wt ~ mpg + drat + am, mtcars)
+
+

In R, the lm function produces models of class “lm”:

+
+
class(mod[[1]])
+
+
[1] "lm"
+
+
+

Let’s say you would like to print the dependent variable for each model of this particular class. All you need to do is define a new method called glance_custom.lm. This method should return a data.frame (or tibble) with 1 row, and 1 column per piece of information you want to display. For example:

+
+
glance_custom.lm <- function(x, ...) {
+    dv <- as.character(formula(x)[2])
+    out <- data.frame("DV" = dv)
+    return(out)
+}
+
+

Now, let’s customize the body of the table. The vcov argument already allows users to customize uncertainty estimates. But imagine you want to override the coefficient estimates of your “lm” models. Easy! All you need to do is define a tidy_custom.lm method which returns a data.frame (or tibble) with one column called “term” and one column called “estimate”.

+

Here, we’ll substitute estimates by an up/down-pointing triangles which represents their signs:

+
+
tidy_custom.lm <- function(x, ...) {
+    s <- summary(x)$coefficients
+    out <- data.frame(
+      term = row.names(s),
+      estimate = ifelse(s[,1] > 0, '▲', '▼'))
+    return(out)
+}
+
+

After you define the glance_custom and tidy_custom methods, modelsummary will automatically display your customized model information:

+
+ +
+ + + + + +tinytable_9fk3qlzheod0kheqfysh + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)(2)
(Intercept)
(55.415)(0.728)
mpg
(1.792) (0.019)
drat
(20.198)(0.245)
am
(0.240)
Num.Obs. 32 32
R2 0.614 0.803
R2 Adj. 0.588 0.782
AIC 337.9 46.4
BIC 343.7 53.7
Log.Lik. -164.940-18.201
F 23.100 38.066
RMSE 41.91 0.43
DV hp wt
+
+ + +
+
+

Note that you can define a std.error column in tidy_custom.lm to replace the uncertainty estimates instead of the coefficients.

+

Customization: New model class

+

An even more fundamental way to customize the output would be to completely bypass modelsummary’s extractor functions by assigning a new class name to your model. For example,

+
+
# estimate a linear model
+mod_custom <- lm(hp ~ mpg + drat, mtcars)
+
+# assign it a new class
+class(mod_custom) <- "custom"
+
+# define tidy and glance methods
+tidy.custom <- function(x, ...) {
+  data.frame(
+    term = names(coef(x)),
+    estimate = letters[1:length(coef(x))],
+    std.error = seq_along(coef(x))
+  )
+}
+
+glance.custom <- function(x, ...) {
+  data.frame(
+    "Model" = "Custom",
+    "nobs" = stats:::nobs.lm(x)
+  )
+}
+
+# summarize
+modelsummary(mod_custom)
+
+ + + + + +tinytable_zcojavccn7wsaent64n4 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
(1)
(Intercept)a
(1.000)
mpg b
(2.000)
drat c
(3.000)
Num.Obs. 32
Model Custom
+
+ + +
+
+

Warning: When defining new tidy and glance methods, it is important to include an ellipsis argument (...).

+

Note that in the glance.custom() method, we called stats:::nobs.lm() instead of the default stats::nobs() method, because the latter know does not know where to dispatch models of our new “custom” class. Being more explicit solves the problem.

+

An alternative would be to set a new class that inherits from the previous one, and to use a global option to set broom as the default extractor function (otherwise modelsummary will use its standard lm extractors by inheritance):

+
+
options(modelsummary_get = "broom")
+class(mod_custom) <- c("custom", "lm")
+
+

Customization: modelsummary_list +

+

Another flexible way to customize model output is to use output = "modelsummary_list". With this output option, modelsummary() returns a list with two elements: tidy contains parameter estimates, standard errors, etc., and glance contains model statistics such as the AIC. For example,

+
+
mod <- lm(hp ~ mpg + drat, mtcars)
+mod_list <- modelsummary(mod, output = "modelsummary_list")
+mod_list$tidy
+
+
         term   estimate std.error  statistic df.error      p.value s.value group conf.low conf.high
+1 (Intercept) 278.515455 55.414866  5.0260061       29 2.359726e-05    15.4             NA        NA
+2         mpg  -9.985499  1.791837 -5.5727709       29 5.172030e-06    17.6             NA        NA
+3        drat  19.125752 20.197756  0.9469246       29 3.515013e-01     1.5             NA        NA
+
+
mod_list$glance
+
+
       aic      bic r.squared adj.r.squared     rmse nobs        F    logLik
+1 337.8809 343.7438 0.6143611     0.5877653 41.90687   32 23.09994 -164.9404
+
+
+

Both tidy and glance can now be customized, and the updated model can be passed back to modelsummary using modelsummary(mod_list). All information that is displayed in the table is contained in mod_list, so this pattern allows for very flexible adjustments of output tables.

+

A useful example for this pattern concerns mixed models using lme4. Assume we want to compare the effect of using different degrees-of-freedom adjustments on the significance of the coefficients. The models have identical parameter estimates, standard errors, and model fit statistics - we only want to change the p-values. We use the parameters package to compute the adjusted p-values.

+
+
library("lme4")
+mod <- lmer(mpg ~ drat + (1 | am), data = mtcars)
+mod_list <- modelsummary(mod, output = "modelsummary_list", effects = "fixed")
+# create a copy, where we'll change the p-values
+mod_list_kenward <- as.list(mod_list)
+mod_list_kenward$tidy$p.value <- parameters::p_value_kenward(mod)$p
+
+modelsummary(list("Wald" = mod_list, "Kenward" = mod_list_kenward), 
+            statistic = "{std.error} ({p.value}) {stars}")
+
+ + + + + +tinytable_o3yljn4kcrac80bwor9a + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
WaldKenward
(Intercept)-5.159 -5.159
6.409 (0.428) 6.409 (0.680)
drat 7.045 7.045
1.736 ( + 1.736 (0.086) +
Num.Obs. 32 32
R2 Marg. 0.402 0.402
R2 Cond. 0.440 0.440
AIC 188.7 188.7
BIC 194.6 194.6
ICC 0.1 0.1
RMSE 4.28 4.28
+
+ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/vignettes/modelsummary_files/figure-html/unnamed-chunk-58-1.png b/docs/vignettes/modelsummary_files/figure-html/unnamed-chunk-58-1.png new file mode 100644 index 000000000..510dd36f6 Binary files /dev/null and b/docs/vignettes/modelsummary_files/figure-html/unnamed-chunk-58-1.png differ diff --git a/docs/vignettes/modelsummary_files/figure-html/unnamed-chunk-59-1.png b/docs/vignettes/modelsummary_files/figure-html/unnamed-chunk-59-1.png new file mode 100644 index 000000000..c902bb4f2 Binary files /dev/null and b/docs/vignettes/modelsummary_files/figure-html/unnamed-chunk-59-1.png differ diff --git a/docs/vignettes/tinytable_assets/id2f7w7u9d9rzuy7hjbmh5.png b/docs/vignettes/tinytable_assets/id2f7w7u9d9rzuy7hjbmh5.png new file mode 100644 index 000000000..1560aef70 Binary files /dev/null and b/docs/vignettes/tinytable_assets/id2f7w7u9d9rzuy7hjbmh5.png differ diff --git a/docs/vignettes/tinytable_assets/id5n35g19pfypd7fokhgci.png b/docs/vignettes/tinytable_assets/id5n35g19pfypd7fokhgci.png new file mode 100644 index 000000000..e9a59f3d7 Binary files /dev/null and b/docs/vignettes/tinytable_assets/id5n35g19pfypd7fokhgci.png differ diff --git a/docs/vignettes/tinytable_assets/id6d3n4yp5m7fbo4bxkgu9.png b/docs/vignettes/tinytable_assets/id6d3n4yp5m7fbo4bxkgu9.png new file mode 100644 index 000000000..73baabf5e Binary files /dev/null and b/docs/vignettes/tinytable_assets/id6d3n4yp5m7fbo4bxkgu9.png differ diff --git a/docs/vignettes/tinytable_assets/id707b2ig9c581vshogi7u.png b/docs/vignettes/tinytable_assets/id707b2ig9c581vshogi7u.png new file mode 100644 index 000000000..2f1fb5257 Binary files /dev/null and b/docs/vignettes/tinytable_assets/id707b2ig9c581vshogi7u.png differ diff --git a/docs/vignettes/tinytable_assets/idbr784doc9d8t89lot46j.png b/docs/vignettes/tinytable_assets/idbr784doc9d8t89lot46j.png new file mode 100644 index 000000000..760becf8f Binary files /dev/null and b/docs/vignettes/tinytable_assets/idbr784doc9d8t89lot46j.png differ diff --git a/docs/vignettes/tinytable_assets/idbt4aqy60su2usom4g50p.png b/docs/vignettes/tinytable_assets/idbt4aqy60su2usom4g50p.png new file mode 100644 index 000000000..4e1ff0a72 Binary files /dev/null and b/docs/vignettes/tinytable_assets/idbt4aqy60su2usom4g50p.png differ diff --git a/docs/vignettes/tinytable_assets/ide1skfboc59qvda8h19mm.png b/docs/vignettes/tinytable_assets/ide1skfboc59qvda8h19mm.png new file mode 100644 index 000000000..45b78f751 Binary files /dev/null and b/docs/vignettes/tinytable_assets/ide1skfboc59qvda8h19mm.png differ diff --git a/docs/vignettes/tinytable_assets/idgprmqp5nwk1d7viismav.png b/docs/vignettes/tinytable_assets/idgprmqp5nwk1d7viismav.png new file mode 100644 index 000000000..868de0a0f Binary files /dev/null and b/docs/vignettes/tinytable_assets/idgprmqp5nwk1d7viismav.png differ diff --git a/docs/vignettes/tinytable_assets/idgx1n35y78blkxbopyluy.png b/docs/vignettes/tinytable_assets/idgx1n35y78blkxbopyluy.png new file mode 100644 index 000000000..938c99a0d Binary files /dev/null and b/docs/vignettes/tinytable_assets/idgx1n35y78blkxbopyluy.png differ diff --git a/docs/vignettes/tinytable_assets/idiz8d7npq3coha886vzxm.png b/docs/vignettes/tinytable_assets/idiz8d7npq3coha886vzxm.png new file mode 100644 index 000000000..eeec9ad35 Binary files /dev/null and b/docs/vignettes/tinytable_assets/idiz8d7npq3coha886vzxm.png differ diff --git a/docs/vignettes/tinytable_assets/idja94iaib2k9bfntkevm4.png b/docs/vignettes/tinytable_assets/idja94iaib2k9bfntkevm4.png new file mode 100644 index 000000000..b3b581202 Binary files /dev/null and b/docs/vignettes/tinytable_assets/idja94iaib2k9bfntkevm4.png differ diff --git a/docs/vignettes/tinytable_assets/idjpoxlwkpwae9hf2qnbn0.png b/docs/vignettes/tinytable_assets/idjpoxlwkpwae9hf2qnbn0.png new file mode 100644 index 000000000..e0b4c89b2 Binary files /dev/null and b/docs/vignettes/tinytable_assets/idjpoxlwkpwae9hf2qnbn0.png differ diff --git a/docs/vignettes/tinytable_assets/idk1411n9y0vmsemjf8qa9.png b/docs/vignettes/tinytable_assets/idk1411n9y0vmsemjf8qa9.png new file mode 100644 index 000000000..5fb35cb54 Binary files /dev/null and b/docs/vignettes/tinytable_assets/idk1411n9y0vmsemjf8qa9.png differ diff --git a/docs/vignettes/tinytable_assets/idlluih07206itwa05tdgn.png b/docs/vignettes/tinytable_assets/idlluih07206itwa05tdgn.png new file mode 100644 index 000000000..98112fa9c Binary files /dev/null and b/docs/vignettes/tinytable_assets/idlluih07206itwa05tdgn.png differ diff --git a/docs/vignettes/tinytable_assets/idom079d22d8p9rjdim0jj.png b/docs/vignettes/tinytable_assets/idom079d22d8p9rjdim0jj.png new file mode 100644 index 000000000..0deeb5196 Binary files /dev/null and b/docs/vignettes/tinytable_assets/idom079d22d8p9rjdim0jj.png differ diff --git a/docs/vignettes/tinytable_assets/idsdmvxtukw6wdvskwppn2.png b/docs/vignettes/tinytable_assets/idsdmvxtukw6wdvskwppn2.png new file mode 100644 index 000000000..1e7a9f616 Binary files /dev/null and b/docs/vignettes/tinytable_assets/idsdmvxtukw6wdvskwppn2.png differ diff --git a/docs/vignettes/tinytable_assets/idvdudp6e5pjx0llw4au1w.png b/docs/vignettes/tinytable_assets/idvdudp6e5pjx0llw4au1w.png new file mode 100644 index 000000000..8648ddbfd Binary files /dev/null and b/docs/vignettes/tinytable_assets/idvdudp6e5pjx0llw4au1w.png differ diff --git a/inst/tinytest/_tinysnapshot/escape-caption_notes.txt b/inst/tinytest/_tinysnapshot/escape-caption_notes.txt index ecf95990e..9f53c6f66 100644 --- a/inst/tinytest/_tinysnapshot/escape-caption_notes.txt +++ b/inst/tinytest/_tinysnapshot/escape-caption_notes.txt @@ -1,7 +1,7 @@ \begin{table} -\caption{banana\_fish} \centering \begin{talltblr}[ %% tabularray outer open +caption={banana\_fish}, entry=none,label=none, note{}={foo\_bar}, note{}={hello\_world}, diff --git a/inst/tinytest/_tinysnapshot/escape-issue707_01.txt b/inst/tinytest/_tinysnapshot/escape-issue707_01.txt index 708834135..25ffd2d3f 100644 --- a/inst/tinytest/_tinysnapshot/escape-issue707_01.txt +++ b/inst/tinytest/_tinysnapshot/escape-issue707_01.txt @@ -1,7 +1,7 @@ \begin{table} -\caption{blah\_blah} \centering -\begin{tblr}[ %% tabularray outer open +\begin{talltblr}[ %% tabularray outer open +caption={blah\_blah}, ] %% tabularray outer close { %% tabularray inner open colspec={Q[]Q[]}, @@ -15,5 +15,5 @@ column{2}={halign=c,}, hp & \num{-0.068} \\ & (\num{0.010}) \\ \bottomrule -\end{tblr} +\end{talltblr} \end{table} diff --git a/inst/tinytest/_tinysnapshot/escape-issue707_02.txt b/inst/tinytest/_tinysnapshot/escape-issue707_02.txt index 8827c6d43..de9dcfcd7 100644 --- a/inst/tinytest/_tinysnapshot/escape-issue707_02.txt +++ b/inst/tinytest/_tinysnapshot/escape-issue707_02.txt @@ -1,7 +1,7 @@ \begin{table} -\caption{blah\_blah} \centering -\begin{tblr}[ %% tabularray outer open +\begin{talltblr}[ %% tabularray outer open +caption={blah\_blah}, ] %% tabularray outer close { %% tabularray inner open colspec={Q[]Q[]Q[]}, @@ -14,5 +14,5 @@ column{3}={halign=r,}, mpg & \num{20.09} & \num{6.03} \\ hp & \num{146.69} & \num{68.56} \\ \bottomrule -\end{tblr} +\end{talltblr} \end{table} diff --git a/inst/tinytest/_tinysnapshot/escape-issue707_03.txt b/inst/tinytest/_tinysnapshot/escape-issue707_03.txt index aef088dfe..1500c66d0 100644 --- a/inst/tinytest/_tinysnapshot/escape-issue707_03.txt +++ b/inst/tinytest/_tinysnapshot/escape-issue707_03.txt @@ -1,7 +1,7 @@ \begin{table} -\caption{blah_blah} \centering -\begin{tblr}[ %% tabularray outer open +\begin{talltblr}[ %% tabularray outer open +caption={blah_blah}, ] %% tabularray outer close { %% tabularray inner open colspec={Q[]Q[]}, @@ -15,5 +15,5 @@ column{2}={halign=c,}, hp & \num{-0.068} \\ & (\num{0.010}) \\ \bottomrule -\end{tblr} +\end{talltblr} \end{table} diff --git a/inst/tinytest/_tinysnapshot/escape-issue707_04.txt b/inst/tinytest/_tinysnapshot/escape-issue707_04.txt index 6b16412f1..bc3288390 100644 --- a/inst/tinytest/_tinysnapshot/escape-issue707_04.txt +++ b/inst/tinytest/_tinysnapshot/escape-issue707_04.txt @@ -1,7 +1,7 @@ \begin{table} -\caption{blah_blah} \centering -\begin{tblr}[ %% tabularray outer open +\begin{talltblr}[ %% tabularray outer open +caption={blah_blah}, ] %% tabularray outer close { %% tabularray inner open colspec={Q[]Q[]Q[]}, @@ -14,5 +14,5 @@ column{3}={halign=r,}, mpg & \num{20.09} & \num{6.03} \\ hp & \num{146.69} & \num{68.56} \\ \bottomrule -\end{tblr} +\end{talltblr} \end{table} diff --git a/inst/tinytest/_tinysnapshot/escape-latex_tabular_escape_false.txt b/inst/tinytest/_tinysnapshot/escape-latex_tabular_escape_false.txt new file mode 100644 index 000000000..f69813c23 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/escape-latex_tabular_escape_false.txt @@ -0,0 +1,14 @@ +\begin{tblr}[ %% tabularray outer open +] %% tabularray outer close +{ %% tabularray inner open +colspec={Q[]Q[]}, +column{1}={halign=l,}, +column{2}={halign=l,}, +} %% tabularray inner close +\toprule +a & {} \\ \midrule %% TinyTableHeader +\num{1.00} & 4 \\ +\num{2.00} & \times 5 \\ +\num{3.00} & 6 \\ +\bottomrule +\end{tblr} diff --git a/inst/tinytest/_tinysnapshot/escape-latex_tabular_escape_true.txt b/inst/tinytest/_tinysnapshot/escape-latex_tabular_escape_true.txt new file mode 100644 index 000000000..e9fbc4a62 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/escape-latex_tabular_escape_true.txt @@ -0,0 +1,14 @@ +\begin{tblr}[ %% tabularray outer open +] %% tabularray outer close +{ %% tabularray inner open +colspec={Q[]Q[]}, +column{1}={halign=l,}, +column{2}={halign=l,}, +} %% tabularray inner close +\toprule +a & \{\} \\ \midrule %% TinyTableHeader +\num{1.00} & 4 \\ +\num{2.00} & \textbackslash{}times 5 \\ +\num{3.00} & 6 \\ +\bottomrule +\end{tblr} diff --git a/inst/tinytest/_tinysnapshot/escape-panel_escape_FALSE.txt b/inst/tinytest/_tinysnapshot/escape-panel_escape_FALSE.txt index e50fac1c6..9d873baf5 100644 --- a/inst/tinytest/_tinysnapshot/escape-panel_escape_FALSE.txt +++ b/inst/tinytest/_tinysnapshot/escape-panel_escape_FALSE.txt @@ -1,5 +1,5 @@ -\caption{$\beta_1$} -\begin{tblr}[ %% tabularray outer open +\begin{talltblr}[ %% tabularray outer open +caption={$\beta_1$}, ] %% tabularray outer close { %% tabularray inner open colspec={Q[]Q[]Q[]}, @@ -37,7 +37,7 @@ column{3}={halign=c,}, } %% tabularray inner close \toprule & A_B & B_C \\ \midrule %% TinyTableHeader -Panel B: $\log(3)^2$ &&& \\ +Panel B: $\log(3)^2$ && \\ (Intercept) & -5.114 & 48.324 \\ & (10.030) & (11.103) \\ a_b & 1.412 & -0.887 \\ @@ -51,7 +51,7 @@ AIC & 204.6 & 180.3 \\ BIC & 209.0 & 186.2 \\ Log.Lik. & -99.294 & -86.170 \\ RMSE & 5.39 & 3.57 \\ -Panel B: $\log(3)_2$ &&& \\ +Panel B: $\log(3)_2$ && \\ (Intercept) & 767.619 & -340.780 \\ & (204.642) & (221.689) \\ a_b & -30.080 & 17.599 \\ @@ -66,4 +66,4 @@ BIC & 402.0 & 377.8 \\ Log.Lik. & -195.797 & -181.979 \\ RMSE & 109.92 & 71.37 \\ \bottomrule -\end{tblr} +\end{talltblr} diff --git a/inst/tinytest/_tinysnapshot/escape-panel_escape_TRUE.txt b/inst/tinytest/_tinysnapshot/escape-panel_escape_TRUE.txt index af7a433bd..07a412455 100644 --- a/inst/tinytest/_tinysnapshot/escape-panel_escape_TRUE.txt +++ b/inst/tinytest/_tinysnapshot/escape-panel_escape_TRUE.txt @@ -1,5 +1,5 @@ -\caption{\$\textbackslash{}beta\_1\$} -\begin{tblr}[ %% tabularray outer open +\begin{talltblr}[ %% tabularray outer open +caption={\$\textbackslash{}beta\_1\$}, ] %% tabularray outer close { %% tabularray inner open colspec={Q[]Q[]Q[]}, @@ -37,7 +37,7 @@ column{3}={halign=c,}, } %% tabularray inner close \toprule & A\_B & B\_C \\ \midrule %% TinyTableHeader -Panel B: $\log(3)^2$ &&& \\ +Panel B: $\log(3)^2$ && \\ (Intercept) & -5.114 & 48.324 \\ & (10.030) & (11.103) \\ a\_b & 1.412 & -0.887 \\ @@ -51,7 +51,7 @@ AIC & 204.6 & 180.3 \\ BIC & 209.0 & 186.2 \\ Log.Lik. & -99.294 & -86.170 \\ RMSE & 5.39 & 3.57 \\ -Panel B: $\log(3)_2$ &&& \\ +Panel B: $\log(3)_2$ && \\ (Intercept) & 767.619 & -340.780 \\ & (204.642) & (221.689) \\ a\_b & -30.080 & 17.599 \\ @@ -66,4 +66,4 @@ BIC & 402.0 & 377.8 \\ Log.Lik. & -195.797 & -181.979 \\ RMSE & 109.92 & 71.37 \\ \bottomrule -\end{tblr} +\end{talltblr} diff --git a/inst/tinytest/_tinysnapshot_review/modelplot-coef_map_color_shape_background.png b/inst/tinytest/_tinysnapshot_review/modelplot-coef_map_color_shape_background.png new file mode 100644 index 000000000..18b7b1990 Binary files /dev/null and b/inst/tinytest/_tinysnapshot_review/modelplot-coef_map_color_shape_background.png differ diff --git a/inst/tinytest/_tinysnapshot_review/modelplot-coef_omit.png b/inst/tinytest/_tinysnapshot_review/modelplot-coef_omit.png new file mode 100644 index 000000000..506c9d94f Binary files /dev/null and b/inst/tinytest/_tinysnapshot_review/modelplot-coef_omit.png differ diff --git a/inst/tinytest/_tinysnapshot_review/modelplot-multiple_plots_vanilla.png b/inst/tinytest/_tinysnapshot_review/modelplot-multiple_plots_vanilla.png new file mode 100644 index 000000000..0e218d507 Binary files /dev/null and b/inst/tinytest/_tinysnapshot_review/modelplot-multiple_plots_vanilla.png differ diff --git a/inst/tinytest/_tinysnapshot_review/modelplot-vanilla.png b/inst/tinytest/_tinysnapshot_review/modelplot-vanilla.png new file mode 100644 index 000000000..232420bea Binary files /dev/null and b/inst/tinytest/_tinysnapshot_review/modelplot-vanilla.png differ diff --git a/inst/tinytest/_tinysnapshot_review/modeplot-model_order.png b/inst/tinytest/_tinysnapshot_review/modeplot-model_order.png new file mode 100644 index 000000000..34622e821 Binary files /dev/null and b/inst/tinytest/_tinysnapshot_review/modeplot-model_order.png differ diff --git a/inst/tinytest/_tinysnapshot_review/modeplot-multiple_plots_facet.png b/inst/tinytest/_tinysnapshot_review/modeplot-multiple_plots_facet.png new file mode 100644 index 000000000..865d9d37b Binary files /dev/null and b/inst/tinytest/_tinysnapshot_review/modeplot-multiple_plots_facet.png differ diff --git a/inst/tinytest/qayztocfynadtqlpmxceqftkvpwjih.pdf b/inst/tinytest/qayztocfynadtqlpmxceqftkvpwjih.pdf new file mode 100644 index 000000000..cac13423c Binary files /dev/null and b/inst/tinytest/qayztocfynadtqlpmxceqftkvpwjih.pdf differ diff --git a/inst/tinytest/test-coef_map.R b/inst/tinytest/test-coef_map.R index 08400c5cd..dda37a4bb 100644 --- a/inst/tinytest/test-coef_map.R +++ b/inst/tinytest/test-coef_map.R @@ -70,4 +70,16 @@ mat <- modelsummary(models, coef_map = cm) expect_inherits(mat, "data.frame") -expect_equivalent(dim(mat), c(19, 5)) \ No newline at end of file +expect_equivalent(dim(mat), c(19, 5)) + + +# Isuee #757 +requiet("lme4") +sleepstudy_fit <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy) +tab <- modelsummary( + sleepstudy_fit, + coef_map = c("SD (Observations)", "(Intercept)"), + output = "dataframe" +) +expect_equivalent(tab$term[1:3], c("SD (Observations)", "(Intercept)", "(Intercept)")) +expect_equivalent(tab$statistic[1:3], c("estimate", "estimate", "std.error")) diff --git a/inst/tinytest/test-datasummary_balance.R b/inst/tinytest/test-datasummary_balance.R index 65218a362..8047050b1 100644 --- a/inst/tinytest/test-datasummary_balance.R +++ b/inst/tinytest/test-datasummary_balance.R @@ -321,3 +321,9 @@ training <- training %>% Married) tab <- datasummary_balance(~ Treatment, training, fmt = 3, stars = TRUE, align = "lllllldl", output = "latex") expect_snapshot_print(tab, "datasummary_balance-issue711") + + +# Issue #751 +tab <- datasummary_balance(mpg + hp ~ am, data = mtcars, output = "dataframe") +expect_equal(nrow(tab), 2) + diff --git a/inst/tinytest/test-escape.R b/inst/tinytest/test-escape.R index 8b6ac227d..12425b73b 100644 --- a/inst/tinytest/test-escape.R +++ b/inst/tinytest/test-escape.R @@ -167,6 +167,17 @@ expect_snapshot_print( modelsummary(mod, output = "latex", escape = TRUE), "escape-hat_I_formula") + +# Issue# #740: escape not respected in `datasummary_df()` +tbl <- data.frame("a"=c(1,2,3), "{}" = c(4,"\\times 5",6), check.names = FALSE) +expect_snapshot_print( + datasummary_df(tbl, output = "latex_tabular", escape = FALSE), + "escape-latex_tabular_escape_false") +expect_snapshot_print( + datasummary_df(tbl, output = "latex_tabular", escape = TRUE), + "escape-latex_tabular_escape_true") + + requiet("fixest") base <- iris names(base) <- c("y", paste0("x", 1:3), "fe1") @@ -187,4 +198,4 @@ expect_snapshot_print(tab, "escape-issue707_02") tab <- modelsummary(mod, title = "blah_blah", gof_map = NA, output = "latex", escape = FALSE) expect_snapshot_print(tab, "escape-issue707_03") tab <- datasummary(mpg + hp ~ mean + sd, title = "blah_blah", data = mtcars, output = "latex", escape = FALSE) -expect_snapshot_print(tab, "escape-issue707_04") \ No newline at end of file +expect_snapshot_print(tab, "escape-issue707_04") diff --git a/inst/tinytest/test-flextable.R b/inst/tinytest/test-flextable.R index e78993f0c..d7b3f24c0 100644 --- a/inst/tinytest/test-flextable.R +++ b/inst/tinytest/test-flextable.R @@ -10,4 +10,19 @@ models[['Logit 2']] <- glm(am ~ hp + disp, mtcars, family = binomial()) # no error with caption and notes tab <- modelsummary(models, "flextable", title = "test title", notes = "test note", stars = TRUE) -expect_inherits(tab, "flextable") \ No newline at end of file +expect_inherits(tab, "flextable") + + + +# # Issue #761 +# d <- data.frame(x = rnorm(100), y = rnorm(100)) +# res <- list( +# lm(y ~ x, data = d), +# lm(y ~ x + I(x^2), data = d) +# ) +# modelsummary( +# res, +# output = "flextable", +# estimate = c(ABC = "estimate"), +# shape = term ~ model + statistic +# ) diff --git a/inst/tinytest/test-kableExtra.R b/inst/tinytest/test-kableExtra.R index 0541588d8..7a9ec376d 100644 --- a/inst/tinytest/test-kableExtra.R +++ b/inst/tinytest/test-kableExtra.R @@ -63,6 +63,20 @@ tab <- modelsummary(mod, "latex", title = "blah_cyl", escape = FALSE) expect_false(grepl("blah\\\\_cyl", tab)) +# Issue #761 +# d <- data.frame(x = rnorm(100), y = rnorm(100)) +# res <- list( +# lm(y ~ x, data = d), +# lm(y ~ x + I(x^2), data = d) +# ) +# modelsummary( +# res, +# output = "kableExtra", +# estimate = c(ABC = "estimate"), +# shape = term ~ model + statistic +# ) + + options(modelsummary_factory_default = NULL) options(modelsummary_factory_html = NULL) diff --git a/inst/tinytest/test-labels.R b/inst/tinytest/test-labels.R index 1ed2f963d..b90ad1f1c 100644 --- a/inst/tinytest/test-labels.R +++ b/inst/tinytest/test-labels.R @@ -110,3 +110,11 @@ mod <- list( tab <- modelsummary(dvnames(mod), "dataframe", coef_rename = TRUE) expect_equivalent(names(tab)[4:5], c("Miles per gallon", "hp")) expect_true("Number of cylinders" %in% tab$term) + + +# Issue #752 +requiet("labelled") +v2 <- labelled( c(0L, 0L, 1L), labels = c(yes = 1, no = 0)) +dat <- data.frame(v2, y = 1:3) +tab <- datasummary(y ~ Mean, dat) +expect_inherits(tab, "tinytable") diff --git a/inst/tinytest/test-shape.R b/inst/tinytest/test-shape.R index a6b63c073..10e93104e 100644 --- a/inst/tinytest/test-shape.R +++ b/inst/tinytest/test-shape.R @@ -292,11 +292,12 @@ tab <- modelsummary( mod, output = "dataframe", shape = term + model ~ statistic, - statistic = c("std.error", "{p.value}{stars}", "{estimate} ({statistic})"), + estimate = c("$\\hat{\\beta}$" = "{estimate}"), + statistic = c("S.E." = "std.error", "p" = "{p.value}{stars}", "Est. (t)" = "{estimate} ({statistic})"), fmt = fmt_statistic(estimate = 3, p.value = 2)) expect_equivalent( colnames(tab), - c("part", "term", "model", "Est.", "S.E.", "p", "Est. (t)")) + c("part", "term", "model", "$\\hat{\\beta}$", "S.E.", "p", "Est. (t)")) # Issue #631: bad group column diff --git a/man-roxygen/options.R b/man-roxygen/options.R index f20f2eb37..cba8615cf 100644 --- a/man-roxygen/options.R +++ b/man-roxygen/options.R @@ -26,9 +26,10 @@ #' format, you can use ' the `options` function: #' #' `options(modelsummary_factory_html = 'kableExtra')` -#' `options(modelsummary_factory_latex = 'gt')` #' `options(modelsummary_factory_word = 'huxtable')` #' `options(modelsummary_factory_png = 'gt')` +#' `options(modelsummary_factory_latex = 'gt')` +#' `options(modelsummary_factory_latex_tabular = 'kableExtra')` #' #' ### Table themes #' diff --git a/man/datasummary_balance.Rd b/man/datasummary_balance.Rd index 987eddaaa..cfc896af8 100644 --- a/man/datasummary_balance.Rd +++ b/man/datasummary_balance.Rd @@ -23,9 +23,11 @@ datasummary_balance( ) } \arguments{ -\item{formula}{a one-sided formula with the "condition" or "column" variable -on the right-hand side. ~1 can be used to show summary statistics for the -full data set} +\item{formula}{\itemize{ +\item \code{~1}: show summary statistics for the full dataset +\item one-sided formula: with the "condition" or "column" variable on the right-hand side. +\item two-side formula: with the subset of variables to summarize on the left-hand side and the condition variable on the right-hand side. +}} \item{data}{A data.frame (or tibble). If this data includes columns called "blocks", "clusters", and/or "weights", the "estimatr" package will consider diff --git a/man/get_estimates.Rd b/man/get_estimates.Rd index b560c9d76..810c9b6bd 100644 --- a/man/get_estimates.Rd +++ b/man/get_estimates.Rd @@ -25,7 +25,7 @@ argument accepts six types of input (see the 'Details' and 'Examples' sections below): \itemize{ \item NULL returns the default uncertainty estimates of the model object -\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. +\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the \code{sandwich::vcovBS()}. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. \item function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., \code{stats::vcov}, \code{sandwich::vcovHC}, \code{function(x) vcovPC(x, cluster="country")}). \item formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid). \item named list of \code{length(models)} variance-covariance matrices with row and column names equal to the names of your coefficient estimates. diff --git a/man/get_gof.Rd b/man/get_gof.Rd index 9b3f32cf0..c9fd8d629 100644 --- a/man/get_gof.Rd +++ b/man/get_gof.Rd @@ -4,11 +4,13 @@ \alias{get_gof} \title{Extract goodness-of-fit statistics a tidy format.} \usage{ -get_gof(model, vcov_type = NULL, ...) +get_gof(model, gof_function = NULL, vcov_type = NULL, ...) } \arguments{ \item{model}{a single model object} +\item{gof_function}{function which accepts a model object in the \code{model} argument and returns a 1-row \code{data.frame} with one custom goodness-of-fit statistic per column.} + \item{vcov_type}{string vcov type to add at the bottom of the table} \item{...}{all other arguments are passed through to three functions. See the documentation of these functions for lists of available arguments. diff --git a/man/get_vcov.Rd b/man/get_vcov.Rd index 87270723f..22337b6c2 100644 --- a/man/get_vcov.Rd +++ b/man/get_vcov.Rd @@ -14,7 +14,7 @@ argument accepts six types of input (see the 'Details' and 'Examples' sections below): \itemize{ \item NULL returns the default uncertainty estimates of the model object -\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. +\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the \code{sandwich::vcovBS()}. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. \item function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., \code{stats::vcov}, \code{sandwich::vcovHC}, \code{function(x) vcovPC(x, cluster="country")}). \item formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid). \item named list of \code{length(models)} variance-covariance matrices with row and column names equal to the names of your coefficient estimates. diff --git a/man/get_vcov.mlm.Rd b/man/get_vcov.mlm.Rd index 2948b1a8b..ee284f039 100644 --- a/man/get_vcov.mlm.Rd +++ b/man/get_vcov.mlm.Rd @@ -14,7 +14,7 @@ argument accepts six types of input (see the 'Details' and 'Examples' sections below): \itemize{ \item NULL returns the default uncertainty estimates of the model object -\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. +\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the \code{sandwich::vcovBS()}. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. \item function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., \code{stats::vcov}, \code{sandwich::vcovHC}, \code{function(x) vcovPC(x, cluster="country")}). \item formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid). \item named list of \code{length(models)} variance-covariance matrices with row and column names equal to the names of your coefficient estimates. diff --git a/man/modelplot.Rd b/man/modelplot.Rd index c332f1533..97682cde7 100644 --- a/man/modelplot.Rd +++ b/man/modelplot.Rd @@ -75,7 +75,7 @@ argument accepts six types of input (see the 'Details' and 'Examples' sections below): \itemize{ \item NULL returns the default uncertainty estimates of the model object -\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. +\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the \code{sandwich::vcovBS()}. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. \item function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., \code{stats::vcov}, \code{sandwich::vcovHC}, \code{function(x) vcovPC(x, cluster="country")}). \item formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid). \item named list of \code{length(models)} variance-covariance matrices with row and column names equal to the names of your coefficient estimates. diff --git a/man/modelsummary.Rd b/man/modelsummary.Rd index 693a1dd26..af3a31b2a 100644 --- a/man/modelsummary.Rd +++ b/man/modelsummary.Rd @@ -20,6 +20,7 @@ modelsummary( coef_rename = FALSE, gof_map = NULL, gof_omit = NULL, + gof_function = NULL, group_map = NULL, add_columns = NULL, add_rows = NULL, @@ -91,21 +92,25 @@ the data.frame produced by \code{get_estimates(model)}, and strings with curly b \item \code{"{estimate} [{conf.low}, {conf.high}]"} }} -\item{statistic}{vector of strings or \code{glue} strings which select uncertainty -statistics to report vertically below the estimate. NULL omits all -uncertainty statistics. +\item{statistic}{vector of strings or \code{glue} strings which select uncertainty statistics to report vertically below the estimate. NULL omits all uncertainty statistics. \itemize{ -\item "conf.int", "std.error", "statistic", "p.value", "conf.low", "conf.high", . -or any column name produced by \code{get_estimates(model)} +\item "conf.int", "std.error", "statistic", "p.value", "conf.low", "conf.high", or any column name produced by \code{get_estimates(model)} \item \code{glue} package strings with braces, with or without R functions, such as: \itemize{ \item \code{"{p.value} [{conf.low}, {conf.high}]"} \item \code{"Std.Error: {std.error}"} \item \code{"{exp(estimate) * std.error}"} -} \item Numbers are automatically rounded and converted to strings. To apply functions to their numeric values, as in the last \code{glue} example, users must set \code{fmt=NULL}. \item Parentheses are added automatically unless the string includes \code{glue} curly braces \code{{}}. +} +\item Notes: +\itemize{ +\item The names of the \code{statistic} are used a column names when using the \code{shape} argument to display statistics as columns: +\itemize{ +\item \code{statistic=c("p"="p.value", "["="conf.low", "]"="conf.high")} +} \item Some statistics are not supported for all models. See column names in \code{get_estimates(model)}, and visit the website to learn how to add custom statistics. +} }} \item{vcov}{robust standard errors and other manual statistics. The \code{vcov} @@ -113,7 +118,7 @@ argument accepts six types of input (see the 'Details' and 'Examples' sections below): \itemize{ \item NULL returns the default uncertainty estimates of the model object -\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. +\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the \code{sandwich::vcovBS()}. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. \item function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., \code{stats::vcov}, \code{sandwich::vcovHC}, \code{function(x) vcovPC(x, cluster="country")}). \item formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid). \item named list of \code{length(models)} variance-covariance matrices with row and column names equal to the names of your coefficient estimates. @@ -212,6 +217,8 @@ model information. This argument accepts 4 types of values: \item \code{"^(?!.*IC)"}: keep statistics matching the "IC" substring. }} +\item{gof_function}{function which accepts a model object in the \code{model} argument and returns a 1-row \code{data.frame} with one custom goodness-of-fit statistic per column.} + \item{group_map}{named or unnamed character vector. Subset, rename, and reorder coefficient groups specified a grouping variable specified in the \code{shape} argument formula. This argument behaves like \code{coef_map}.} diff --git a/man/msummary.Rd b/man/msummary.Rd index d15386090..2ea732600 100644 --- a/man/msummary.Rd +++ b/man/msummary.Rd @@ -20,6 +20,7 @@ msummary( coef_rename = FALSE, gof_map = NULL, gof_omit = NULL, + gof_function = NULL, group_map = NULL, add_columns = NULL, add_rows = NULL, @@ -91,21 +92,25 @@ the data.frame produced by \code{get_estimates(model)}, and strings with curly b \item \code{"{estimate} [{conf.low}, {conf.high}]"} }} -\item{statistic}{vector of strings or \code{glue} strings which select uncertainty -statistics to report vertically below the estimate. NULL omits all -uncertainty statistics. +\item{statistic}{vector of strings or \code{glue} strings which select uncertainty statistics to report vertically below the estimate. NULL omits all uncertainty statistics. \itemize{ -\item "conf.int", "std.error", "statistic", "p.value", "conf.low", "conf.high", . -or any column name produced by \code{get_estimates(model)} +\item "conf.int", "std.error", "statistic", "p.value", "conf.low", "conf.high", or any column name produced by \code{get_estimates(model)} \item \code{glue} package strings with braces, with or without R functions, such as: \itemize{ \item \code{"{p.value} [{conf.low}, {conf.high}]"} \item \code{"Std.Error: {std.error}"} \item \code{"{exp(estimate) * std.error}"} -} \item Numbers are automatically rounded and converted to strings. To apply functions to their numeric values, as in the last \code{glue} example, users must set \code{fmt=NULL}. \item Parentheses are added automatically unless the string includes \code{glue} curly braces \code{{}}. +} +\item Notes: +\itemize{ +\item The names of the \code{statistic} are used a column names when using the \code{shape} argument to display statistics as columns: +\itemize{ +\item \code{statistic=c("p"="p.value", "["="conf.low", "]"="conf.high")} +} \item Some statistics are not supported for all models. See column names in \code{get_estimates(model)}, and visit the website to learn how to add custom statistics. +} }} \item{vcov}{robust standard errors and other manual statistics. The \code{vcov} @@ -113,7 +118,7 @@ argument accepts six types of input (see the 'Details' and 'Examples' sections below): \itemize{ \item NULL returns the default uncertainty estimates of the model object -\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. +\item string, vector, or (named) list of strings. "iid", "classical", and "constant" are aliases for \code{NULL}, which returns the model's default uncertainty estimates. The strings "HC", "HC0", "HC1" (alias: "stata"), "HC2", "HC3" (alias: "robust"), "HC4", "HC4m", "HC5", "HAC", "NeweyWest", "Andrews", "panel-corrected", "outer-product", and "weave" use variance-covariance matrices computed using functions from the \code{sandwich} package, or equivalent method. "BS", "bootstrap", "residual", "mammen", "webb", "xy", "wild" use the \code{sandwich::vcovBS()}. The behavior of those functions can (and sometimes \emph{must}) be altered by passing arguments to \code{sandwich} directly from \code{modelsummary} through the ellipsis (\code{...}), but it is safer to define your own custom functions as described in the next bullet. \item function or (named) list of functions which return variance-covariance matrices with row and column names equal to the names of your coefficient estimates (e.g., \code{stats::vcov}, \code{sandwich::vcovHC}, \code{function(x) vcovPC(x, cluster="country")}). \item formula or (named) list of formulas with the cluster variable(s) on the right-hand side (e.g., ~clusterid). \item named list of \code{length(models)} variance-covariance matrices with row and column names equal to the names of your coefficient estimates. @@ -212,6 +217,8 @@ model information. This argument accepts 4 types of values: \item \code{"^(?!.*IC)"}: keep statistics matching the "IC" substring. }} +\item{gof_function}{function which accepts a model object in the \code{model} argument and returns a 1-row \code{data.frame} with one custom goodness-of-fit statistic per column.} + \item{group_map}{named or unnamed character vector. Subset, rename, and reorder coefficient groups specified a grouping variable specified in the \code{shape} argument formula. This argument behaves like \code{coef_map}.} diff --git a/vignettes/datasummary.qmd b/vignettes/datasummary.qmd index 4becd4d8d..5484cf3a5 100644 --- a/vignettes/datasummary.qmd +++ b/vignettes/datasummary.qmd @@ -2,11 +2,6 @@ title: "Data Summaries" format: html: default - # pdf: - # toc: true - # number-sections: true - # colorlinks: true - # keep-tex: true --- ```{css, echo = FALSE} diff --git a/vignettes/get_started.qmd b/vignettes/get_started.qmd index 9b5bb44de..109c7c283 100644 --- a/vignettes/get_started.qmd +++ b/vignettes/get_started.qmd @@ -2,11 +2,6 @@ title: "Getting started" format: html: default - # pdf: - # toc: true - # number-sections: true - # colorlinks: true - # keep-tex: true --- ```{css, echo = FALSE} diff --git a/vignettes/modelplot.qmd b/vignettes/modelplot.qmd index c924b4a7d..cb9f4a9a1 100644 --- a/vignettes/modelplot.qmd +++ b/vignettes/modelplot.qmd @@ -2,11 +2,6 @@ title: "Model Plots" format: html: default - pdf: - toc: true - number-sections: true - colorlinks: true - keep-tex: true --- diff --git a/vignettes/modelsummary.qmd b/vignettes/modelsummary.qmd index 7ee619c8c..984c768d3 100644 --- a/vignettes/modelsummary.qmd +++ b/vignettes/modelsummary.qmd @@ -2,11 +2,6 @@ title: "Model Summaries" format: html: default - # pdf: - # toc: true - # number-sections: true - # colorlinks: true - # keep-tex: true --- ```{css, echo=FALSE} @@ -480,6 +475,51 @@ modelsummary( escape = FALSE) ``` +# `gof_function` + +The `gof_function` argument accepts a function which processes the model and returns a data frame with custom information about each model. For example, we can insert a row in the bottom portion of the table to display the dependent variable with: + +```{r} +mod <- list( + lm(mpg ~ qsec + drat, mtcars), + lm(hp ~ qsec + drat, mtcars) +) + +fun <- function(model) data.frame("DV" = insight::find_response(model)) + +modelsummary(mod, gof_function = fun) +``` + +In this example, we write a function factory to insert an indicator for whether a model includes control variables: + +```{r} +mod <- list( + lm(wt ~ qsec, data = mtcars), + lm(wt ~ qsec + hp + mpg, data = mtcars) +) + +check_controls <- function(variables, yes = "✓", no = "") { + checkmate::assert_character(variables, min.len = 1) + checkmate::assert_string(no) + checkmate::assert_string(yes) + reg <- paste0("^", paste(variables, collapse = "$|^"), "$") + fun <- function(model) { + est <- get_estimates(model) + df <- if (all(variables %in% est$term)) yes else no + df <- data.frame(Controls = df) + return(df) + } + list("fun" = fun, "regex" = reg) +} + +cc <- check_controls(c("hp", "mpg")) + +modelsummary(mod, + gof_function = cc$fun, + coef_omit = cc$regex) +``` + + # `shape` This section requires version 1.3.1 of `modelsummary`. If this version is not available on CRAN yet, you can install the development version by following [the instructions on the website.](https://modelsummary.com/#installation) @@ -633,7 +673,7 @@ modelsummary( estimate = c("$\\hat{\\beta}$" = "estimate"), statistic = c("$\\sigma_{\\hat{\\beta}}$" = "std.error"), shape = term ~ model + statistic) - ``` +``` ### `fixest` @@ -971,64 +1011,56 @@ modelsummary(mod, output = "gt") # Case studies -## Subgroup estimation with `nest_by` +## Collapse control variables into an indicator -Sometimes, it is useful to estimate multiple regression models on subsets of the data. To do this efficiently, we can use the `nest_by` function from the `dplyr` package. Then, estimate the models with `lm`, extract them and name them with `pull`, and finally summarize them with `modelsummary`: +In some cases, analysts want to display a single checkmark in their table if a full set of control variables is available. This can easily be achieved with the `glance_custom` mechanism described in detail in [the extension vignette.](modelsummary_extension.html) Here is a simple example: -```{r, message=FALSE, warning=FALSE} -library(tidyverse) +```{r} +library(modelsummary) -mtcars %>% - nest_by(cyl) %>% - mutate(models = list(lm(mpg ~ hp, data))) %>% - pull(models, name = cyl) %>% - modelsummary -``` +mod <- list( + glm(am ~ hp + factor(cyl), data = mtcars, family = binomial), + lm(mpg ~ hp + factor(cyl) + gear + qsec, data = mtcars) +) -## Statistics in separate columns instead of one over the other +glance_custom.lm <- function(x, ...) { + controls <- c("gear", "qsec") + if (all(controls %in% names(coef(x)))) { + out <- data.frame(Controls = "✓") + } else { + out <- data.frame(Controls = "✗") + } + return(out) +} -In somes cases, you may want to display statistics in separate columns instead of one over the other. It is easy to achieve this outcome by using the `estimate` argument. This argument accepts a vector of values, one for each of the models we are trying to summarize. If we want to include estimates and standard errors in separate columns, all we need to do is repeat a model, but request different statistics. For example, +glance_custom.glm <- glance_custom.lm -```{r} -library(tinytable) +modelsummary(mod, "html", coef_omit = "qsec|gear") +``` -mod1 <- lm(mpg ~ hp, mtcars) -mod2 <- lm(mpg ~ hp + drat, mtcars) -models <- list( - "Coef." = mod1, - "Std.Error" = mod1, - "Coef." = mod2, - "Std.Error" = mod2) +Return to nomal: -modelsummary(models, - output = "tinytable", - estimate = c("estimate", "std.error", "estimate", "std.error"), - statistic = NULL, - gof_omit = ".*") |> - group_tt(j = list("Model A" = 2:3, "Model B" = 4:5)) +```{r} +rm(list = c("glance_custom.glm", "glance_custom.lm")) ``` -This can be automated using a simple function: -```{r} -side_by_side <- function(models, estimates, ...) { - models <- rep(models, each = length(estimates)) - estimates <- rep(estimates, times = 2) - names(models) <- names(estimates) - modelsummary(models = models, estimate = estimates, - statistic = NULL, gof_omit = ".*", ...) -} +## Subgroup estimation with `nest_by` -models = list( - lm(mpg ~ hp, mtcars), - lm(mpg ~ hp + drat, mtcars)) +Sometimes, it is useful to estimate multiple regression models on subsets of the data. To do this efficiently, we can use the `nest_by` function from the `dplyr` package. Then, estimate the models with `lm`, extract them and name them with `pull`, and finally summarize them with `modelsummary`: +```{r, message=FALSE, warning=FALSE} -estimates <- c("Coef." = "estimate", "Std.Error" = "std.error") +library(tidyverse) -side_by_side(models, estimates = estimates) +mtcars %>% + nest_by(cyl) %>% + mutate(models = list(lm(mpg ~ hp, data))) %>% + pull(models, name = cyl) %>% + modelsummary ``` + ## Bootstrap Users often want to use estimates or standard errors that have been obtained using a custom strategy. To achieve this in an automated and replicable way, it can be useful to use the `tidy_custom` strategy described above in the "Cutomizing Existing Models" section. diff --git a/vignettes/modelsummary_extension.qmd b/vignettes/modelsummary_extension.qmd index ec4a192c2..c797613a8 100644 --- a/vignettes/modelsummary_extension.qmd +++ b/vignettes/modelsummary_extension.qmd @@ -1,12 +1,5 @@ --- title: "Extension and Customization" -format: - html: default - pdf: - toc: true - number-sections: true - colorlinks: true - keep-tex: true --- ```{css, echo = FALSE}