diff --git a/R/tm_missing_data.R b/R/tm_missing_data.R
index d57c616bd..71e9cad50 100644
--- a/R/tm_missing_data.R
+++ b/R/tm_missing_data.R
@@ -17,6 +17,17 @@
#'
#' @inherit shared_params return
#'
+#' @section Decorating `tm_missing_data`:
+#'
+#' This module generates the following objects, which can be modified in place using decorators:
+#' - `summary_plot` (`ggplot2 plot grob`)
+#' - `combination_plot` (`ggplot2 plot grob`)
+#' - `by_subject_plot` (`ggplot2`)
+#' - `table` ([DT::datatable()])
+#'
+#' For additional details and examples of decorators, refer to the vignette
+#' `vignette("decorate-modules-output", package = "teal")` or the [`teal_transform_module()`] documentation.
+#'
#' @examplesShinylive
#' library(teal.modules.general)
#' interactive <- function() TRUE
@@ -87,7 +98,8 @@ tm_missing_data <- function(label = "Missing data",
"Combinations Main" = teal.widgets::ggplot2_args(labs = list(title = NULL))
),
pre_output = NULL,
- post_output = NULL) {
+ post_output = NULL,
+ decorators = NULL) {
message("Initializing tm_missing_data")
# Requires Suggested packages
@@ -121,14 +133,28 @@ tm_missing_data <- function(label = "Missing data",
checkmate::assert_multi_class(pre_output, c("shiny.tag", "shiny.tag.list", "html"), null.ok = TRUE)
checkmate::assert_multi_class(post_output, c("shiny.tag", "shiny.tag.list", "html"), null.ok = TRUE)
+
+ available_decorators <- c("summary_plot", "summary_plot", "combination_plot", "by_subject_plot", "summary_table")
+ if (checkmate::test_list(decorators, "teal_transform_module", null.ok = TRUE)) {
+ decorators <- if (checkmate::test_names(names(decorators), subset.of = c("default", available_decorators))) {
+ lapply(decorators, list)
+ } else {
+ list(default = decorators)
+ }
+ }
+ assert_decorators(decorators, null.ok = TRUE, names = c("default", available_decorators))
# End of assertions
ans <- module(
label,
server = srv_page_missing_data,
server_args = list(
- parent_dataname = parent_dataname, plot_height = plot_height,
- plot_width = plot_width, ggplot2_args = ggplot2_args, ggtheme = ggtheme
+ parent_dataname = parent_dataname,
+ plot_height = plot_height,
+ plot_width = plot_width,
+ ggplot2_args = ggplot2_args,
+ ggtheme = ggtheme,
+ decorators = decorators
),
ui = ui_page_missing_data,
datanames = "all",
@@ -165,7 +191,7 @@ ui_page_missing_data <- function(id, pre_output = NULL, post_output = NULL) {
# Server function for the missing data module (all datasets)
srv_page_missing_data <- function(id, data, reporter, filter_panel_api, parent_dataname,
- plot_height, plot_width, ggplot2_args, ggtheme) {
+ plot_height, plot_width, ggplot2_args, ggtheme, decorators) {
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI")
moduleServer(id, function(input, output, session) {
@@ -215,7 +241,8 @@ srv_page_missing_data <- function(id, data, reporter, filter_panel_api, parent_d
id = ns(x),
summary_per_patient = if_subject_plot,
ggtheme = ggtheme,
- datanames = datanames
+ datanames = datanames,
+ decorators = decorators
)
)
}
@@ -248,7 +275,8 @@ srv_page_missing_data <- function(id, data, reporter, filter_panel_api, parent_d
parent_dataname = parent_dataname,
plot_height = plot_height,
plot_width = plot_width,
- ggplot2_args = ggplot2_args
+ ggplot2_args = ggplot2_args,
+ decorators = decorators
)
}
)
@@ -326,7 +354,7 @@ ui_missing_data <- function(id, by_subject_plot = FALSE) {
}
# UI encoding for the missing data module (all datasets)
-encoding_missing_data <- function(id, summary_per_patient = FALSE, ggtheme, datanames) {
+encoding_missing_data <- function(id, summary_per_patient = FALSE, ggtheme, datanames, decorators) {
ns <- NS(id)
tagList(
@@ -381,25 +409,30 @@ encoding_missing_data <- function(id, summary_per_patient = FALSE, ggtheme, data
),
value = FALSE
)
- }
+ },
+ ui_decorate_teal_data(ns("dec_summary_plot"), decorators = subset_decorators("summary_plot", decorators))
),
conditionalPanel(
is_tab_active_js(ns("summary_type"), "Combinations"),
- uiOutput(ns("cutoff"))
+ uiOutput(ns("cutoff")),
+ ui_decorate_teal_data(ns("dec_combination_plot"), decorators = subset_decorators("combination_plot", decorators))
+ ),
+ conditionalPanel(
+ is_tab_active_js(ns("summary_type"), "Grouped by Subject"),
+ ui_decorate_teal_data(ns("dec_by_subject_plot"), decorators = subset_decorators("by_subject_plot", decorators))
),
conditionalPanel(
is_tab_active_js(ns("summary_type"), "By Variable Levels"),
- tagList(
- uiOutput(ns("group_by_var_ui")),
- uiOutput(ns("group_by_vals_ui")),
- radioButtons(
- ns("count_type"),
- label = "Display missing as",
- choices = c("counts", "proportions"),
- selected = "counts",
- inline = TRUE
- )
- )
+ uiOutput(ns("group_by_var_ui")),
+ uiOutput(ns("group_by_vals_ui")),
+ radioButtons(
+ ns("count_type"),
+ label = "Display missing as",
+ choices = c("counts", "proportions"),
+ selected = "counts",
+ inline = TRUE
+ ),
+ ui_decorate_teal_data(ns("dec_summary_table"), decorators = subset_decorators("summary_table", decorators))
),
teal.widgets::panel_item(
title = "Plot settings",
@@ -414,241 +447,24 @@ encoding_missing_data <- function(id, summary_per_patient = FALSE, ggtheme, data
)
}
-# Server function for the missing data (single dataset)
-srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, parent_dataname,
- plot_height, plot_width, ggplot2_args) {
- with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
- with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI")
- checkmate::assert_class(data, "reactive")
- checkmate::assert_class(isolate(data()), "teal_data")
+srv_summary_plot <- function(id,
+ data_r,
+ data_keys,
+ common_code_q,
+ data_parent_keys,
+ ggplot2_args,
+ # inputs
+ summary_type_r,
+ any_na_r,
+ ggtheme_r,
+ if_patients_plot_r) {
moduleServer(id, function(input, output, session) {
- ns <- session$ns
-
- prev_group_by_var <- reactiveVal("")
- data_r <- reactive(data()[[dataname]])
- data_keys <- reactive(unlist(teal.data::join_keys(data())[[dataname]]))
-
- iv_r <- reactive({
- iv <- shinyvalidate::InputValidator$new()
- iv$add_rule(
- "variables_select",
- shinyvalidate::sv_required("At least one reference variable needs to be selected.")
- )
- iv$add_rule(
- "variables_select",
- ~ if (length(setdiff((.), data_keys())) < 1) "Please also select non-key columns."
- )
- iv_summary_table <- shinyvalidate::InputValidator$new()
- iv_summary_table$condition(~ isTRUE(input$summary_type == "By Variable Levels"))
- iv_summary_table$add_rule("count_type", shinyvalidate::sv_required("Please select type of counts"))
- iv_summary_table$add_rule(
- "group_by_vals",
- shinyvalidate::sv_required("Please select both group-by variable and values")
- )
- iv_summary_table$add_rule(
- "group_by_var",
- ~ if (length(.) > 0 && length(input$variables_select) == 1 && (.) == input$variables_select) {
- "If only one reference variable is selected it must not be the grouping variable."
- }
- )
- iv_summary_table$add_rule(
- "variables_select",
- ~ if (length(input$group_by_var) > 0 && length(.) == 1 && (.) == input$group_by_var) {
- "If only one reference variable is selected it must not be the grouping variable."
- }
- )
- iv$add_validator(iv_summary_table)
- iv$enable()
- iv
- })
-
-
- data_parent_keys <- reactive({
- if (length(parent_dataname) > 0 && parent_dataname %in% names(data())) {
- keys <- teal.data::join_keys(data())[[dataname]]
- if (parent_dataname %in% names(keys)) {
- keys[[parent_dataname]]
- } else {
- keys[[dataname]]
- }
- } else {
- NULL
- }
- })
-
- common_code_q <- reactive({
- teal::validate_inputs(iv_r())
-
- group_var <- input$group_by_var
- anl <- data_r()
-
- qenv <- if (!is.null(selected_vars()) && length(selected_vars()) != ncol(anl)) {
- teal.code::eval_code(
- data(),
- substitute(
- expr = ANL <- anl_name[, selected_vars, drop = FALSE],
- env = list(anl_name = as.name(dataname), selected_vars = selected_vars())
- )
- )
- } else {
- teal.code::eval_code(
- data(),
- substitute(expr = ANL <- anl_name, env = list(anl_name = as.name(dataname)))
- )
- }
-
- if (input$summary_type == "By Variable Levels" && !is.null(group_var) && !(group_var %in% selected_vars())) {
- qenv <- teal.code::eval_code(
- qenv,
- substitute(
- expr = ANL[[group_var]] <- anl_name[[group_var]],
- env = list(group_var = group_var, anl_name = as.name(dataname))
- )
- )
- }
-
- new_col_name <- "**anyna**"
-
- qenv <- teal.code::eval_code(
- qenv,
- substitute(
- expr =
- create_cols_labels <- function(cols, just_label = FALSE) {
- column_labels <- column_labels_value
- column_labels[is.na(column_labels) | length(column_labels) == 0] <- ""
- if (just_label) {
- labels <- column_labels[cols]
- } else {
- labels <- ifelse(cols == new_col_name | cols == "", cols, paste0(column_labels[cols], " [", cols, "]"))
- }
- labels
- },
- env = list(
- new_col_name = new_col_name,
- column_labels_value = c(teal.data::col_labels(data_r())[selected_vars()],
- new_col_name = new_col_name
- )
- )
- )
- )
- qenv
- })
-
- selected_vars <- reactive({
- req(input$variables_select)
- keys <- data_keys()
- vars <- unique(c(keys, input$variables_select))
- vars
- })
-
- vars_summary <- reactive({
- na_count <- data_r() %>%
- sapply(function(x) mean(is.na(x)), USE.NAMES = TRUE) %>%
- sort(decreasing = TRUE)
-
- tibble::tibble(
- key = names(na_count),
- value = unname(na_count),
- label = cut(na_count, breaks = seq(from = 0, to = 1, by = 0.1), include.lowest = TRUE)
- )
- })
-
- output$variables <- renderUI({
- choices <- split(x = vars_summary()$key, f = vars_summary()$label, drop = TRUE) %>% rev()
- selected <- choices <- unname(unlist(choices))
-
- teal.widgets::optionalSelectInput(
- ns("variables_select"),
- label = "Select variables",
- label_help = HTML(paste0("Dataset: ", tags$code(dataname))),
- choices = teal.transform::variable_choices(data_r(), choices),
- selected = selected,
- multiple = TRUE
- )
- })
-
- observeEvent(input$filter_na, {
- choices <- vars_summary() %>%
- dplyr::select(!!as.name("key")) %>%
- getElement(name = 1)
-
- selected <- vars_summary() %>%
- dplyr::filter(!!as.name("value") > 0) %>%
- dplyr::select(!!as.name("key")) %>%
- getElement(name = 1)
-
- teal.widgets::updateOptionalSelectInput(
- session = session,
- inputId = "variables_select",
- choices = teal.transform::variable_choices(data_r()),
- selected = restoreInput(ns("variables_select"), selected)
- )
- })
-
- output$group_by_var_ui <- renderUI({
- all_choices <- teal.transform::variable_choices(data_r())
- cat_choices <- all_choices[!sapply(data_r(), function(x) is.numeric(x) || inherits(x, "POSIXct"))]
- validate(
- need(cat_choices, "Dataset does not have any non-numeric or non-datetime variables to use to group data with")
- )
- teal.widgets::optionalSelectInput(
- ns("group_by_var"),
- label = "Group by variable",
- choices = cat_choices,
- selected = `if`(
- is.null(isolate(input$group_by_var)),
- cat_choices[1],
- isolate(input$group_by_var)
- ),
- multiple = FALSE,
- label_help = paste0("Dataset: ", dataname)
- )
- })
-
- output$group_by_vals_ui <- renderUI({
- req(input$group_by_var)
-
- choices <- teal.transform::value_choices(data_r(), input$group_by_var, input$group_by_var)
- prev_choices <- isolate(input$group_by_vals)
-
- # determine selected value based on filtered data
- # display those previously selected values that are still available
- selected <- if (!is.null(prev_choices) && any(prev_choices %in% choices)) {
- prev_choices[match(choices[choices %in% prev_choices], prev_choices)]
- } else if (
- !is.null(prev_choices) &&
- !any(prev_choices %in% choices) &&
- isolate(prev_group_by_var()) == input$group_by_var
- ) {
- # if not any previously selected value is available and the grouping variable is the same,
- # then display NULL
- NULL
- } else {
- # if new grouping variable (i.e. not any previously selected value is available),
- # then display all choices
- choices
- }
-
- prev_group_by_var(input$group_by_var) # set current group_by_var
- validate(need(length(choices) < 100, "Please select group-by variable with fewer than 100 unique values"))
-
- teal.widgets::optionalSelectInput(
- ns("group_by_vals"),
- label = "Filter levels",
- choices = choices,
- selected = selected,
- multiple = TRUE,
- label_help = paste0("Dataset: ", dataname)
- )
- })
-
summary_plot_q <- reactive({
- req(input$summary_type == "Summary") # needed to trigger show r code update on tab change
+ req(summary_type_r() == "Summary") # needed to trigger show r code update on tab change
teal::validate_has_data(data_r(), 1)
qenv <- common_code_q()
-
- if (input$any_na) {
+ if (any_na_r()) {
new_col_name <- "**anyna**"
qenv <- teal.code::eval_code(
qenv,
@@ -692,7 +508,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
)
# always set "**anyna**" level as the last one
- if (isolate(input$any_na)) {
+ if (isolate(any_na_r())) {
qenv <- teal.code::eval_code(
qenv,
quote(x_levels <- c(setdiff(x_levels, "**anyna**"), "**anyna**"))
@@ -712,13 +528,13 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
parsed_ggplot2_args <- teal.widgets::parse_ggplot2_args(
all_ggplot2_args,
- ggtheme = input$ggtheme
+ ggtheme = ggtheme_r()
)
qenv <- teal.code::eval_code(
qenv,
substitute(
- p1 <- summary_plot_obs %>%
+ summary_plot_top <- summary_plot_obs %>%
ggplot() +
aes(
x = factor(create_cols_labels(col), levels = x_levels),
@@ -753,7 +569,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
)
)
- if (isTRUE(input$if_patients_plot)) {
+ if (isTRUE(if_patients_plot_r())) {
qenv <- teal.code::eval_code(
qenv,
substitute(
@@ -794,13 +610,13 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
parsed_ggplot2_args <- teal.widgets::parse_ggplot2_args(
all_ggplot2_args,
- ggtheme = input$ggtheme
+ ggtheme = ggtheme_r()
)
qenv <- teal.code::eval_code(
qenv,
substitute(
- p2 <- summary_plot_patients %>%
+ summary_plot_bottom <- summary_plot_patients %>%
ggplot() +
aes_(
x = ~ factor(create_cols_labels(col), levels = x_levels),
@@ -833,69 +649,42 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
ggthemes = parsed_ggplot2_args$ggtheme
)
)
- ) %>%
- teal.code::eval_code(
- quote({
- g1 <- ggplotGrob(p1)
- g2 <- ggplotGrob(p2)
- g <- gridExtra::gtable_cbind(g1, g2, size = "first")
- g$heights <- grid::unit.pmax(g1$heights, g2$heights)
- grid::grid.newpage()
- })
- )
- } else {
- qenv <- teal.code::eval_code(
- qenv,
- quote({
- g <- ggplotGrob(p1)
- grid::grid.newpage()
- })
)
}
- teal.code::eval_code(
- qenv,
- quote(grid::grid.draw(g))
- )
- })
-
- summary_plot_r <- reactive(summary_plot_q()[["g"]])
-
- combination_cutoff_q <- reactive({
- req(common_code_q())
- teal.code::eval_code(
- common_code_q(),
- quote(
- combination_cutoff <- ANL %>%
- dplyr::mutate_all(is.na) %>%
- dplyr::group_by_all() %>%
- dplyr::tally() %>%
- dplyr::ungroup()
- )
- )
- })
-
- output$cutoff <- renderUI({
- x <- combination_cutoff_q()[["combination_cutoff"]]$n
-
- # select 10-th from the top
- n <- length(x)
- idx <- max(1, n - 10)
- prev_value <- isolate(input$combination_cutoff)
- value <- `if`(
- is.null(prev_value) || prev_value > max(x) || prev_value < min(x),
- sort(x, partial = idx)[idx], prev_value
- )
-
- teal.widgets::optionalSliderInputValMinMax(
- ns("combination_cutoff"),
- "Combination cut-off",
- c(value, range(x))
- )
+ arrange_expr <- if (isTRUE(if_patients_plot_r())) {
+ quote({
+ g1 <- ggplotGrob(summary_plot_top)
+ g2 <- ggplotGrob(summary_plot_bottom)
+ summary_plot <- gridExtra::gtable_cbind(g1, g2, size = "first")
+ summary_plot$heights <- grid::unit.pmax(g1$heights, g2$heights)
+ })
+ } else {
+ quote({
+ g1 <- ggplotGrob(summary_plot_top)
+ summary_plot <- g1
+ })
+ }
+ teal.code::eval_code(qenv, arrange_expr)
})
+ })
+}
+srv_combination_plot <- function(id,
+ data_r,
+ common_code_q,
+ data_keys,
+ data_parent_keys,
+ combination_cutoff_q,
+ ggplot2_args,
+ # inputs
+ summary_type_r,
+ combination_cutoff_r,
+ ggtheme_r,
+ variables_select_r) {
+ moduleServer(id, function(input, output, session) {
combination_plot_q <- reactive({
- req(input$summary_type == "Combinations", input$combination_cutoff, combination_cutoff_q())
+ req(summary_type_r() == "Combinations", combination_cutoff_r(), combination_cutoff_q())
teal::validate_has_data(data_r(), 1)
qenv <- teal.code::eval_code(
@@ -906,12 +695,12 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
dplyr::mutate(id = rank(-n, ties.method = "first")) %>%
tidyr::pivot_longer(-c(n, id), names_to = "key", values_to = "value") %>%
dplyr::arrange(n),
- env = list(combination_cutoff_value = input$combination_cutoff)
+ env = list(combination_cutoff_value = combination_cutoff_r())
)
)
# find keys in dataset not selected in the UI and remove them from dataset
- keys_not_selected <- setdiff(data_keys(), input$variables_select)
+ keys_not_selected <- setdiff(data_keys(), variables_select_r())
if (length(keys_not_selected) > 0) {
qenv <- teal.code::eval_code(
qenv,
@@ -969,14 +758,14 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
parsed_ggplot2_args2 <- teal.widgets::parse_ggplot2_args(
all_ggplot2_args2,
- ggtheme = input$ggtheme
+ ggtheme = ggtheme_r()
)
- teal.code::eval_code(
+ qenv <- teal.code::eval_code(
qenv,
substitute(
expr = {
- p1 <- data_combination_plot_cutoff %>%
+ combination_plot_top <- data_combination_plot_cutoff %>%
dplyr::select(id, n) %>%
dplyr::distinct() %>%
ggplot(aes(x = id, y = n)) +
@@ -994,7 +783,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
graph_number_rows <- length(unique(data_combination_plot_cutoff$id))
graph_number_cols <- nrow(data_combination_plot_cutoff) / graph_number_rows
- p2 <- data_combination_plot_cutoff %>% ggplot() +
+ combination_plot_bottom <- data_combination_plot_cutoff %>% ggplot() +
aes(x = create_cols_labels(key), y = id - 0.5, fill = value) +
geom_tile(alpha = 0.85, height = 0.95) +
scale_fill_manual(
@@ -1008,14 +797,6 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
labs2 +
ggthemes2 +
themes2
-
- g1 <- ggplotGrob(p1)
- g2 <- ggplotGrob(p2)
-
- g <- gridExtra::gtable_rbind(g1, g2, size = "last")
- g$heights[7] <- grid::unit(0.2, "null") # rescale to get the bar chart smaller
- grid::grid.newpage()
- grid::grid.draw(g)
},
env = list(
labs1 = parsed_ggplot2_args1$labs,
@@ -1027,13 +808,34 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
)
)
)
- })
- combination_plot_r <- reactive(combination_plot_q()[["g"]])
+ within(qenv, {
+ g1 <- ggplotGrob(combination_plot_top)
+ g2 <- ggplotGrob(combination_plot_bottom)
+
+ combination_plot <- gridExtra::gtable_rbind(g1, g2, size = "last")
+ combination_plot$heights[7] <- grid::unit(0.2, "null") # rescale to get the bar chart smaller
+ })
+ })
+ })
+}
- summary_table_q <- reactive({
+srv_summary_table <- function(id,
+ data_r,
+ common_code_q,
+ data_keys,
+ data_parent_keys,
+ selected_vars,
+ # inputs
+ summary_type_r,
+ group_by_var_r,
+ group_by_vals_r,
+ variables_select_r,
+ count_type_r) {
+ moduleServer(id, function(input, output, session) {
+ summary_table_q_r <- reactive({
req(
- input$summary_type == "By Variable Levels", # needed to trigger show r code update on tab change
+ summary_type_r() == "By Variable Levels", # needed to trigger show r code update on tab change
common_code_q()
)
teal::validate_has_data(data_r(), 1)
@@ -1041,7 +843,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
# extract the ANL dataset for use in further validation
anl <- common_code_q()[["ANL"]]
- group_var <- input$group_by_var
+ group_var <- group_by_var_r()
validate(
need(
is.null(group_var) ||
@@ -1050,10 +852,10 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
)
)
- group_vals <- input$group_by_vals
- variables_select <- input$variables_select
+ group_vals <- group_by_vals_r()
+ variables_select <- variables_select_r()
vars <- unique(variables_select, group_var)
- count_type <- input$count_type
+ count_type <- count_type_r()
if (!is.null(selected_vars()) && length(selected_vars()) != ncol(anl)) {
variables <- selected_vars()
@@ -1061,17 +863,15 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
variables <- colnames(anl)
}
- summ_fn <- if (input$count_type == "counts") {
+ summ_fn <- if (count_type == "counts") {
function(x) sum(is.na(x))
} else {
function(x) round(sum(is.na(x)) / length(x), 4)
}
- qenv <- common_code_q()
-
- if (!is.null(group_var)) {
- qenv <- teal.code::eval_code(
- qenv,
+ qenv <- if (!is.null(group_var)) {
+ teal.code::eval_code(
+ common_code_q(),
substitute(
expr = {
summary_data <- ANL %>%
@@ -1093,12 +893,13 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
)
)
} else {
- qenv <- teal.code::eval_code(
- qenv,
+ teal.code::eval_code(
+ common_code_q(),
substitute(
expr = summary_data <- ANL %>%
dplyr::summarise_all(summ_fn) %>%
- tidyr::pivot_longer(dplyr::everything(),
+ tidyr::pivot_longer(
+ dplyr::everything(),
names_to = "Variable",
values_to = paste0("Missing (N=", nrow(ANL), ")")
) %>%
@@ -1108,14 +909,24 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
)
}
- teal.code::eval_code(qenv, quote(summary_data))
+ within(qenv, table <- DT::datatable(summary_data))
})
+ })
+}
- summary_table_r <- reactive(summary_table_q()[["summary_data"]])
-
+srv_by_subject_plot <- function(id,
+ data_r,
+ common_code_q,
+ data_keys,
+ data_parent_keys,
+ ggplot2_args,
+ # inputs
+ summary_type_r,
+ ggtheme_r) {
+ moduleServer(id, function(input, output, session) {
by_subject_plot_q <- reactive({
# needed to trigger show r code update on tab change
- req(input$summary_type == "Grouped by Subject", common_code_q())
+ req(summary_type_r() == "Grouped by Subject", common_code_q())
teal::validate_has_data(data_r(), 1)
@@ -1132,7 +943,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
parsed_ggplot2_args <- teal.widgets::parse_ggplot2_args(
all_ggplot2_args,
- ggtheme = input$ggtheme
+ ggtheme = ggtheme_r()
)
teal.code::eval_code(
@@ -1188,7 +999,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
teal.code::eval_code(
substitute(
expr = {
- g <- ggplot(summary_plot_patients, aes(
+ by_subject_plot <- ggplot(summary_plot_patients, aes(
x = factor(id, levels = order_subjects),
y = factor(col, levels = ordered_columns[["column"]]),
fill = isna
@@ -1209,7 +1020,6 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
labs +
ggthemes +
themes
- print(g)
},
env = list(
labs = parsed_ggplot2_args$labs,
@@ -1219,22 +1029,401 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
)
)
})
+ })
+}
+
+# Server function for the missing data (single dataset)
+srv_missing_data <- function(id,
+ data,
+ reporter,
+ filter_panel_api,
+ dataname,
+ parent_dataname,
+ plot_height,
+ plot_width,
+ ggplot2_args,
+ decorators) {
+ with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
+ with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI")
+ checkmate::assert_class(data, "reactive")
+ checkmate::assert_class(isolate(data()), "teal_data")
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
- by_subject_plot_r <- reactive(by_subject_plot_q()[["g"]])
+ prev_group_by_var <- reactiveVal("")
+ data_r <- reactive(data()[[dataname]])
+ data_keys <- reactive(unlist(teal.data::join_keys(data())[[dataname]]))
- output$levels_table <- DT::renderDataTable(
- expr = {
- if (length(input$variables_select) == 0) {
- # so that zeroRecords message gets printed
- # using tibble as it supports weird column names, such as " "
- tibble::tibble(` ` = logical(0))
+ iv_r <- reactive({
+ iv <- shinyvalidate::InputValidator$new()
+ iv$add_rule(
+ "variables_select",
+ shinyvalidate::sv_required("At least one reference variable needs to be selected.")
+ )
+ iv$add_rule(
+ "variables_select",
+ ~ if (length(setdiff((.), data_keys())) < 1) "Please also select non-key columns."
+ )
+ iv_summary_table <- shinyvalidate::InputValidator$new()
+ iv_summary_table$condition(~ isTRUE(input$summary_type == "By Variable Levels"))
+ iv_summary_table$add_rule("count_type", shinyvalidate::sv_required("Please select type of counts"))
+ iv_summary_table$add_rule(
+ "group_by_vals",
+ shinyvalidate::sv_required("Please select both group-by variable and values")
+ )
+ iv_summary_table$add_rule(
+ "group_by_var",
+ ~ if (length(.) > 0 && length(input$variables_select) == 1 && (.) == input$variables_select) {
+ "If only one reference variable is selected it must not be the grouping variable."
+ }
+ )
+ iv_summary_table$add_rule(
+ "variables_select",
+ ~ if (length(input$group_by_var) > 0 && length(.) == 1 && (.) == input$group_by_var) {
+ "If only one reference variable is selected it must not be the grouping variable."
+ }
+ )
+ iv$add_validator(iv_summary_table)
+ iv$enable()
+ iv
+ })
+
+ data_parent_keys <- reactive({
+ if (length(parent_dataname) > 0 && parent_dataname %in% names(data())) {
+ keys <- teal.data::join_keys(data())[[dataname]]
+ if (parent_dataname %in% names(keys)) {
+ keys[[parent_dataname]]
} else {
- summary_table_r()
+ keys[[dataname]]
}
- },
- options = list(language = list(zeroRecords = "No variable selected"), pageLength = input$levels_table_rows)
+ } else {
+ NULL
+ }
+ })
+
+ common_code_q <- reactive({
+ teal::validate_inputs(iv_r())
+
+ group_var <- input$group_by_var
+ anl <- data_r()
+
+ qenv <- if (!is.null(selected_vars()) && length(selected_vars()) != ncol(anl)) {
+ teal.code::eval_code(
+ data(),
+ substitute(
+ expr = ANL <- anl_name[, selected_vars, drop = FALSE],
+ env = list(anl_name = as.name(dataname), selected_vars = selected_vars())
+ )
+ )
+ } else {
+ teal.code::eval_code(
+ data(),
+ substitute(expr = ANL <- anl_name, env = list(anl_name = as.name(dataname)))
+ )
+ }
+
+ if (input$summary_type == "By Variable Levels" && !is.null(group_var) && !(group_var %in% selected_vars())) {
+ qenv <- teal.code::eval_code(
+ qenv,
+ substitute(
+ expr = ANL[[group_var]] <- anl_name[[group_var]],
+ env = list(group_var = group_var, anl_name = as.name(dataname))
+ )
+ )
+ }
+
+ new_col_name <- "**anyna**"
+
+ qenv <- teal.code::eval_code(
+ qenv,
+ substitute(
+ expr =
+ create_cols_labels <- function(cols, just_label = FALSE) {
+ column_labels <- column_labels_value
+ column_labels[is.na(column_labels) | length(column_labels) == 0] <- ""
+ if (just_label) {
+ labels <- column_labels[cols]
+ } else {
+ labels <- ifelse(cols == new_col_name | cols == "", cols, paste0(column_labels[cols], " [", cols, "]"))
+ }
+ labels
+ },
+ env = list(
+ new_col_name = new_col_name,
+ column_labels_value = c(teal.data::col_labels(data_r())[selected_vars()],
+ new_col_name = new_col_name
+ )
+ )
+ )
+ )
+ qenv
+ })
+
+ selected_vars <- reactive({
+ req(input$variables_select)
+ keys <- data_keys()
+ vars <- unique(c(keys, input$variables_select))
+ vars
+ })
+
+ vars_summary <- reactive({
+ na_count <- data_r() %>%
+ sapply(function(x) mean(is.na(x)), USE.NAMES = TRUE) %>%
+ sort(decreasing = TRUE)
+
+ tibble::tibble(
+ key = names(na_count),
+ value = unname(na_count),
+ label = cut(na_count, breaks = seq(from = 0, to = 1, by = 0.1), include.lowest = TRUE)
+ )
+ })
+
+ # Keep encoding panel up-to-date
+ output$variables <- renderUI({
+ choices <- split(x = vars_summary()$key, f = vars_summary()$label, drop = TRUE) %>% rev()
+ selected <- choices <- unname(unlist(choices))
+
+ teal.widgets::optionalSelectInput(
+ ns("variables_select"),
+ label = "Select variables",
+ label_help = HTML(paste0("Dataset: ", tags$code(dataname))),
+ choices = teal.transform::variable_choices(data_r(), choices),
+ selected = selected,
+ multiple = TRUE
+ )
+ })
+
+ observeEvent(input$filter_na, {
+ choices <- vars_summary() %>%
+ dplyr::select(!!as.name("key")) %>%
+ getElement(name = 1)
+
+ selected <- vars_summary() %>%
+ dplyr::filter(!!as.name("value") > 0) %>%
+ dplyr::select(!!as.name("key")) %>%
+ getElement(name = 1)
+
+ teal.widgets::updateOptionalSelectInput(
+ session = session,
+ inputId = "variables_select",
+ choices = teal.transform::variable_choices(data_r()),
+ selected = restoreInput(ns("variables_select"), selected)
+ )
+ })
+
+ output$group_by_var_ui <- renderUI({
+ all_choices <- teal.transform::variable_choices(data_r())
+ cat_choices <- all_choices[!sapply(data_r(), function(x) is.numeric(x) || inherits(x, "POSIXct"))]
+ validate(
+ need(cat_choices, "Dataset does not have any non-numeric or non-datetime variables to use to group data with")
+ )
+ teal.widgets::optionalSelectInput(
+ ns("group_by_var"),
+ label = "Group by variable",
+ choices = cat_choices,
+ selected = `if`(
+ is.null(isolate(input$group_by_var)),
+ cat_choices[1],
+ isolate(input$group_by_var)
+ ),
+ multiple = FALSE,
+ label_help = paste0("Dataset: ", dataname)
+ )
+ })
+
+ output$group_by_vals_ui <- renderUI({
+ req(input$group_by_var)
+
+ choices <- teal.transform::value_choices(data_r(), input$group_by_var, input$group_by_var)
+ prev_choices <- isolate(input$group_by_vals)
+
+ # determine selected value based on filtered data
+ # display those previously selected values that are still available
+ selected <- if (!is.null(prev_choices) && any(prev_choices %in% choices)) {
+ prev_choices[match(choices[choices %in% prev_choices], prev_choices)]
+ } else if (
+ !is.null(prev_choices) &&
+ !any(prev_choices %in% choices) &&
+ isolate(prev_group_by_var()) == input$group_by_var
+ ) {
+ # if not any previously selected value is available and the grouping variable is the same,
+ # then display NULL
+ NULL
+ } else {
+ # if new grouping variable (i.e. not any previously selected value is available),
+ # then display all choices
+ choices
+ }
+
+ prev_group_by_var(input$group_by_var) # set current group_by_var
+ validate(need(length(choices) < 100, "Please select group-by variable with fewer than 100 unique values"))
+ teal.widgets::optionalSelectInput(
+ ns("group_by_vals"),
+ label = "Filter levels",
+ choices = choices,
+ selected = selected,
+ multiple = TRUE,
+ label_help = paste0("Dataset: ", dataname)
+ )
+ })
+
+ combination_cutoff_q <- reactive({
+ req(common_code_q())
+ teal.code::eval_code(
+ common_code_q(),
+ quote(
+ combination_cutoff <- ANL %>%
+ dplyr::mutate_all(is.na) %>%
+ dplyr::group_by_all() %>%
+ dplyr::tally() %>%
+ dplyr::ungroup()
+ )
+ )
+ })
+
+ output$cutoff <- renderUI({
+ x <- combination_cutoff_q()[["combination_cutoff"]]$n
+
+ # select 10-th from the top
+ n <- length(x)
+ idx <- max(1, n - 10)
+ prev_value <- isolate(input$combination_cutoff)
+ value <- `if`(
+ is.null(prev_value) || prev_value > max(x) || prev_value < min(x),
+ sort(x, partial = idx)[idx], prev_value
+ )
+
+ teal.widgets::optionalSliderInputValMinMax(
+ ns("combination_cutoff"),
+ "Combination cut-off",
+ c(value, range(x))
+ )
+ })
+
+ # Common inputs in build functions
+ summary_type_r <- reactive(input$summary_type)
+ ggtheme_r <- reactive(input$ggtheme)
+
+ # Building qenvs
+ summary_plot_q <- srv_summary_plot(
+ "summary_plot",
+ data_r,
+ data_keys,
+ common_code_q,
+ data_parent_keys,
+ ggplot2_args,
+ summary_type_r,
+ reactive(input$any_na),
+ ggtheme_r,
+ reactive(input$if_patients_plot)
+ )
+
+ combination_plot_q <- srv_combination_plot(
+ "combination_plot",
+ data_r,
+ common_code_q,
+ data_keys,
+ data_parent_keys,
+ combination_cutoff_q,
+ ggplot2_args,
+ summary_type_r,
+ reactive(input$combination_cutoff),
+ ggtheme_r,
+ reactive(input$variables_select)
+ )
+
+ summary_table_q <- srv_summary_table(
+ "summary_table",
+ data_r,
+ common_code_q,
+ data_keys,
+ data_parent_keys,
+ selected_vars,
+ summary_type_r,
+ reactive(input$group_by_var),
+ reactive(input$group_by_vals),
+ reactive(input$variables_select),
+ reactive(input$count_type)
)
+ by_subject_plot_q <- srv_by_subject_plot(
+ "by_subject_plot",
+ data_r,
+ common_code_q,
+ data_keys,
+ data_parent_keys,
+ ggplot2_args,
+ summary_type_r,
+ ggtheme_r
+ )
+
+ # Decorated outputs
+
+ # Summary_plot_q
+ decorated_summary_plot_q <- srv_decorate_teal_data(
+ id = "dec_summary_plot",
+ data = summary_plot_q,
+ decorators = subset_decorators("summary_plot", decorators),
+ expr = {
+ grid::grid.newpage()
+ grid::grid.draw(summary_plot)
+ }
+ )
+
+ decorated_combination_plot_q <- srv_decorate_teal_data(
+ id = "dec_combination_plot",
+ data = combination_plot_q,
+ decorators = subset_decorators("combination_plot", decorators),
+ expr = {
+ grid::grid.newpage()
+ grid::grid.draw(combination_plot)
+ }
+ )
+
+ decorated_summary_table_q <- srv_decorate_teal_data(
+ id = "dec_summary_table",
+ data = summary_table_q,
+ decorators = subset_decorators("summary_table", decorators),
+ expr = table
+ )
+
+ decorated_by_subject_plot_q <- srv_decorate_teal_data(
+ id = "dec_by_subject_plot",
+ data = by_subject_plot_q,
+ decorators = subset_decorators("by_subject_plot", decorators),
+ expr = print(by_subject_plot)
+ )
+
+ # Plots & tables reactives
+
+ summary_plot_r <- reactive({
+ req(decorated_summary_plot_q())[["summary_plot"]]
+ })
+
+ combination_plot_r <- reactive({
+ req(decorated_combination_plot_q())[["combination_plot"]]
+ })
+
+ summary_table_r <- reactive({
+ req(decorated_summary_table_q())
+
+ if (length(input$variables_select) == 0) {
+ # so that zeroRecords message gets printed
+ # using tibble as it supports weird column names, such as " "
+ DT::datatable(
+ tibble::tibble(` ` = logical(0)),
+ options = list(language = list(zeroRecords = "No variable selected."), pageLength = input$levels_table_rows)
+ )
+ } else {
+ decorated_summary_table_q()[["table"]]
+ }
+ })
+
+ by_subject_plot_r <- reactive({
+ req(decorated_by_subject_plot_q()[["by_subject_plot"]])
+ })
+
+ # Generate output
pws1 <- teal.widgets::plot_with_settings_srv(
id = "summary_plot",
plot_r = summary_plot_r,
@@ -1249,6 +1438,8 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
width = plot_width
)
+ output$levels_table <- DT::renderDataTable(summary_table_r())
+
pws3 <- teal.widgets::plot_with_settings_srv(
id = "by_subject_plot",
plot_r = by_subject_plot_r,
@@ -1256,23 +1447,22 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
width = plot_width
)
- final_q <- reactive({
- req(input$summary_type)
- sum_type <- input$summary_type
+ decorated_final_q <- reactive({
+ sum_type <- req(input$summary_type)
if (sum_type == "Summary") {
- summary_plot_q()
+ decorated_summary_plot_q()
} else if (sum_type == "Combinations") {
- combination_plot_q()
+ decorated_combination_plot_q()
} else if (sum_type == "By Variable Levels") {
- summary_table_q()
+ decorated_summary_table_q()
} else if (sum_type == "Grouped by Subject") {
- by_subject_plot_q()
+ decorated_by_subject_plot_q()
}
})
teal.widgets::verbatim_popup_srv(
id = "rcode",
- verbatim_content = reactive(teal.code::get_code(final_q())),
+ verbatim_content = reactive(teal.code::get_code(req(decorated_final_q()))),
title = "Show R Code for Missing Data"
)
@@ -1308,7 +1498,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
card$append_text("Comment", "header3")
card$append_text(comment)
}
- card$append_src(teal.code::get_code(final_q()))
+ card$append_src(teal.code::get_code(req(decorated_final_q())))
card
}
teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun)
diff --git a/R/utils.R b/R/utils.R
index ec83a41ee..750911a6a 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -280,3 +280,112 @@ assert_single_selection <- function(x,
}
invisible(TRUE)
}
+
+#' Wrappers around `srv_transform_teal_data` that allows to decorate the data
+#' @inheritParams teal::srv_transform_teal_data
+#' @param expr (`expression` or `reactive`) to evaluate on the output of the decoration.
+#' When an expression it must be inline code. See [within()]
+#' Default is `NULL` which won't evaluate any appending code.
+#' @details
+#' `srv_decorate_teal_data` is a wrapper around `srv_transform_teal_data` that
+#' allows to decorate the data with additional expressions.
+#' When original `teal_data` object is in error state, it will show that error
+#' first.
+#'
+#' @keywords internal
+srv_decorate_teal_data <- function(id, data, decorators, expr) {
+ assert_reactive(data)
+ checkmate::assert_list(decorators, "teal_transform_module")
+
+ missing_expr <- missing(expr)
+ if (!missing_expr) {
+ expr <- rlang::enexpr(expr)
+ }
+
+ moduleServer(id, function(input, output, session) {
+ decorated_output <- srv_transform_teal_data("inner", data = data, transformators = decorators)
+
+ reactive({
+ # ensure original errors are displayed and `eval_code` is never executed with NULL
+ req(data(), decorated_output())
+ if (missing_expr) {
+ decorated_output()
+ } else {
+ eval_code(decorated_output(), expr)
+ }
+ })
+ })
+}
+
+#' @rdname srv_decorate_teal_data
+#' @details
+#' `ui_decorate_teal_data` is a wrapper around `ui_transform_teal_data`.
+#' @keywords internal
+ui_decorate_teal_data <- function(id, decorators, ...) {
+ teal::ui_transform_teal_data(NS(id, "inner"), transformators = decorators, ...)
+}
+
+#' Internal function to check if decorators is a valid object
+#' @noRd
+check_decorators <- function(x, names = NULL, null.ok = FALSE) {
+ checkmate::qassert(null.ok, "B1")
+
+ check_message <- checkmate::check_list(
+ x,
+ null.ok = null.ok,
+ names = "named"
+ )
+
+ if (!is.null(names)) {
+ check_message <- if (isTRUE(check_message)) {
+ out_message <- checkmate::check_names(names(x), subset.of = c("default", names))
+ # see https://github.com/insightsengineering/teal.logger/issues/101
+ if (isTRUE(out_message)) {
+ out_message
+ } else {
+ gsub("\\{", "(", gsub("\\}", ")", out_message))
+ }
+ } else {
+ check_message
+ }
+ }
+
+ if (!isTRUE(check_message)) {
+ return(check_message)
+ }
+
+ valid_elements <- vapply(
+ x,
+ checkmate::test_list,
+ types = "teal_transform_module",
+ null.ok = TRUE,
+ FUN.VALUE = logical(1L)
+ )
+
+ if (all(valid_elements)) {
+ return(TRUE)
+ }
+
+ "May only contain the type 'teal_transform_module' or a named list of 'teal_transform_module'."
+}
+
+#' Internal assertion on decorators
+#' @noRd
+assert_decorators <- checkmate::makeAssertionFunction(check_decorators)
+
+#' Subset decorators based on the scope
+#'
+#' `default` is a protected decorator name that is always included in the output,
+#' if it exists
+#'
+#' @param scope (`character`) a character vector of decorator names to include.
+#' @param decorators (named `list`) of list decorators to subset.
+#'
+#' @return A flat list with all decorators to include.
+#' It can be an empty list if none of the scope exists in `decorators` argument.
+#' @keywords internal
+subset_decorators <- function(scope, decorators) {
+ checkmate::assert_character(scope)
+ scope <- intersect(union("default", scope), names(decorators))
+ c(list(), unlist(decorators[scope], recursive = FALSE))
+}
diff --git a/man/srv_decorate_teal_data.Rd b/man/srv_decorate_teal_data.Rd
new file mode 100644
index 000000000..6d6845aca
--- /dev/null
+++ b/man/srv_decorate_teal_data.Rd
@@ -0,0 +1,32 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{srv_decorate_teal_data}
+\alias{srv_decorate_teal_data}
+\alias{ui_decorate_teal_data}
+\title{Wrappers around \code{srv_transform_teal_data} that allows to decorate the data}
+\usage{
+srv_decorate_teal_data(id, data, decorators, expr)
+
+ui_decorate_teal_data(id, decorators, ...)
+}
+\arguments{
+\item{id}{(\code{character(1)}) Module id}
+
+\item{data}{(\verb{reactive teal_data})}
+
+\item{expr}{(\code{expression} or \code{reactive}) to evaluate on the output of the decoration.
+When an expression it must be inline code. See \code{\link[=within]{within()}}
+Default is \code{NULL} which won't evaluate any appending code.}
+}
+\description{
+Wrappers around \code{srv_transform_teal_data} that allows to decorate the data
+}
+\details{
+\code{srv_decorate_teal_data} is a wrapper around \code{srv_transform_teal_data} that
+allows to decorate the data with additional expressions.
+When original \code{teal_data} object is in error state, it will show that error
+first.
+
+\code{ui_decorate_teal_data} is a wrapper around \code{ui_transform_teal_data}.
+}
+\keyword{internal}
diff --git a/man/subset_decorators.Rd b/man/subset_decorators.Rd
new file mode 100644
index 000000000..9b229dffe
--- /dev/null
+++ b/man/subset_decorators.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{subset_decorators}
+\alias{subset_decorators}
+\title{Subset decorators based on the scope}
+\usage{
+subset_decorators(scope, decorators)
+}
+\arguments{
+\item{scope}{(\code{character}) a character vector of decorator names to include.}
+
+\item{decorators}{(named \code{list}) of list decorators to subset.}
+}
+\value{
+A flat list with all decorators to include.
+It can be an empty list if none of the scope exists in \code{decorators} argument.
+}
+\description{
+\code{default} is a protected decorator name that is always included in the output,
+if it exists
+}
+\keyword{internal}
diff --git a/man/tm_a_pca.Rd b/man/tm_a_pca.Rd
index 5ed58485a..f5d2d052c 100644
--- a/man/tm_a_pca.Rd
+++ b/man/tm_a_pca.Rd
@@ -167,13 +167,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokrcQAxLqkQ11XfxQpFC6cAAesKgiSoHBBsZc1AD6sVA2MUEhRroA7rSkABYq7Km4uiBKurqMcACOgrQ17L6ipMTURIyKEFWOAMoAgow1raLxuv1DI6SiSgC+3UpoqOMq+eyVAZm6ALxbwbibfEIiY3vHwmIbPVW6pDBJUEmoBGmbt7oKYAAKAMIDX0ONw+sV2+ye4VIzA0SVEqDgBGuHxBmWg8DBX0mwzEM0B72RojgIg0YMJxNIsPhiPxyN0BAKRFoBDEYK0LFoUHoIiS9MZzNESNpyNSYNSwGAmMG2NGXwAurKytSwABZQSMfgyQGfMADUSiKDCUhazGMehQCDfIioY1gLBoOBfbpC25yIHOqpkhHkfhgpWq9WavDa3X6w2Ot3umCG2hRPR7BwuGkuiO0ky0ajkRhggByjgAMnmk06XZtut1aCZdOwVJn1JodDZbBUbqIihBWAN0OxlgASBplXuExg6LrzJRgOayoA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokrcQAxLoDCAEQCSAMreuvxQpFC6cAAesKgiSmERBsZc1AD6SVA2ieGRRroA7rSkABYq7Fm4uiBKurqMcACOgrSN7BBipMTURIyKEPUAgr6BADIpDSPjSgC+AwBWRCrpANZwrKKVebYF-HAmUMKk6QT8tKIE6Usr65vA0PBbWXIAuu5oqJMqJex1oXldABeAERXD-PhCESiYG6SHCMR-Qb1XSkGDpKDpVAEbL-FG6BRgAAK3iGhPByPxSVhWXSMVIzA06VEqDgBCR+KpeUeehBhOmY3JeM5ojgIg0sNF4pOLLZHM5+IIpWWBDEsK0LFoUHoIlOytoqq2woV9SyNLywGA-NGgrAr1e1XZhIAQgBZLAAaSwAEZyQSwEMAOKuPD+5wAeUCvgAmoSBiaUXIKQn6lK2eR+LCnWA3Z6fX7+cG48mUzBjrR4rz7E5XJTOUnjSiTLRqORGLCAHKOMaCuv1eOJ-4DAa0Ey6dgqNvqTQ6Gy2WrI0TlCCsIbodifAAkrWqW9FjB0-TmSjAs1eQA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_a_regression.Rd b/man/tm_a_regression.Rd
index 29399feae..868e6562a 100644
--- a/man/tm_a_regression.Rd
+++ b/man/tm_a_regression.Rd
@@ -212,13 +212,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokrcQAxLqkQ11XfxQpFC6cAAesKgiSoHBBsZc1AD6sVA2MUEhRroA7rSkABYq7Km4uiBKurqMcACOgrQ17L6ipMTURIyKEFUAwgDyAEzxugODSgC+3UpoqCMq+eyVAZm6ALwrwbjLfEIiouu6u8JiSz1VuqQwSVBJNRI1oqJWEGcXF9RQ9HD+GwpgWDgDzEzxI-2253ej1QJFEeg2qSS4VIzA0SVEqDgBDe7wuqWg8EO-zG4OWuN0cJEGkOlKxpHRmOxZPJuk+31+un+AGUfnTdFoWLQviJEKTISyCAUiLQCGIiWBBKhggBrOBilkXWkaOD8eWKlVqvDM8kwYSaKLw3QAMQAggAZLnOCEaqomWhhHWHBwuY0XbrkuTO3H3R6iTqHRHI1H0jFYnHk-GwS3Eobqlla0g03lo2NM8Xktk-eU8qmZgWMIX0faio353GS6Wyg4bcuVkRJBsy06pYDAFPjMAAXUHZSZhBIBHBnLAdhqQXgZH+ckDvveGc9f3HFjTGtN1HNIi9Tidq4ubo9uo2todrjrVX9uIf9+W3W6tBMunYKnI0e0cBstgVOcohFBArA2ug7CzAAJA0ZQwXCjA6F0kxKGAEyDkAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXQGEAIgEkAZS9dfihSKF04AA9YVBElUPCDYy5qAH1EqBsEsIijXQB3WlIACxV2TNxdECVdXUY4AEdBWgb2CDFSYmoiRkUIOoBBHwCAGWT64bGlAF9+gCsiFTSAazhWUQrc23z+OBMoYVI0gn5aUQI0xeW1jeBoeE3MuQBdN2h0CZVi9lqQ3N0AF5-uFcH8+EIRKIgboIcIxL8BnVdKQYGkoGkGhIGqJRFYIIjkcjqFB6HBqDCFGAsHBsWI8SQqWCkUScagSKI9MDMmloqRmBo0qJUHACISicjMg8uboqVNRky-hLdJyRBoYarRcdhaLxcq6iSyRTgVSAuStbotCxaKSRIhFSz9QQSksCGJKWAAEIAWSwAGksABGB365GajRwfgen3+oMh0Owo60OIygBig1GAWczITploUUjMIcLiVEv6yrkOYlWJxol6MJ5fIF2pFYtLRKlsBlcpGCrw7bD5vVwPDLd1A6JhvJHrNatIluttrE9v7juVztd7uBVsYNvoIhOLtobqeuWAwB70zALxeVTbYEGAHFXHhZWAswANJlvrCDLwvuRKwnQc50LE0H2feNQxgJMUyLJxs2AuoTHzMDdHTTNXDXZFyzLUtcP6fpaBMXR2BUchm20OAbFsGokVEMoIFYQZ0HYNBUAAEhaKp2I4zlGB0PpZiUMAZheIA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_data_table.Rd b/man/tm_data_table.Rd
index af43a7d14..5661eb2ee 100644
--- a/man/tm_data_table.Rd
+++ b/man/tm_data_table.Rd
@@ -126,13 +126,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXVIhrqu-lCkULpwAB6wqCJKAUEGxlzUAPoxUDbRgcFGugDutKQAFirsKbi6IEq6uoxwAI6CtNXsPqKkxNREjIoQlQ20onG6vaJKAL5dSmioAyp57BX+GboAvAtBuPN8QiL9K5vCYnPdlbqkMMkZiUH0IofHx1ostFDXYomicCIacPzLunQttzuxyGvwIczAAGU4KhuBgADIUCQFBR4XQoqEwngAdVo-GRqJRAAU4EEeAiIEj8ijSkSSbCcXiqQTIag4ARaGIUV0gbo5Osjnc8YkWBIdn8+qR2AQ0JoSL8UQBJLAKiH2Z4iXQAYRlVggXPmlW5vKUXVoJl07BU5GYlh0Nls5SOokKEFYAEF0OxJgASeqlH3vRg6TqjJRgEYAXSAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXQGEAIgEkAZS9dfihSKF04AA9YVBElUPCDYy5qAH1EqBsEsIijXQB3WlIACxV2TNxdECVdXUY4AEdBWgb2CDFSYmoiRkUIOoBBHwCAGWT64bGlAF9+gCsiFTSAazhWUQrc23z+OBMoYVI0gn5aUQI0xeW1jeBoeE3MuQBdN2h0CZVi9lqQ3N0AF5-uFcH8+EIRKIgboIcIxL8BnVdKQYBlcmlwvQRIjkcitCxaFBsWI0qI4CINHB+DC6KJSOwpuNgQRfmAAnZHD4AJp+HwKPC6AWOAKOABCACk+QKqgLRZLpYK5X47M5FbKwIMAOKuJXs5wADQFcjkYKReP4xxYEmhwLpDIIaE0JBhAqZ9mJIm8TqsEGNfzq-UDSn6tBMunYKnIzEsOhsthqSNEZQgrEG6HYaFQABIWlUs9nyYwdH1ZkowDMXkA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_file_viewer.Rd b/man/tm_file_viewer.Rd
index a1617b9db..cf3b5cdd3 100644
--- a/man/tm_file_viewer.Rd
+++ b/man/tm_file_viewer.Rd
@@ -54,8 +54,8 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqX8opKAeNdqAfQ8vG3dPbyNdAHdaUgALFXYgqFxdECVdXSSfTLCME2Z4dgBGRQgAX1KlNFRslRj2dJyvXQBeJuTGviERUVbdLuExBogMjNIYfxNaEX8tWjhImWHR0ZVUQVJ-VE9YvrpRUmWV0ZMian4ZPtFWA7gYPOm4BrBRWFQZqZ6FPF1tggBrKBSPrfPy8ASDcRSCBqajfOS4RrHX4QCRXG7ke6fJ7fV4wd5wSaPUQAejxBKJIgwqFR3xSf0BwLaoLg3HB3TEkmksnhiJGyN0pAAHqR0bcsY9nuSPsSyW8ZVThaQ6b91Iy9MywGCBj0uTCeWAEUjjoJGNQQWBYqRSKhRIgSSSTB5JEQtI7ZfxGIIJKT1vR9rE4PwSQAFIiMLz+uCGAAiRAIgngZEMADFwzBPIYAMqoOAEWhTAieKwQcSofgmb7GjKlFa13SlUoF3TsFTkZiWHQ2WxpfmieIQVgAQXQ7GqABJBLQUhPRDIdIxSmUlGAygBdIA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_front_page.Rd b/man/tm_front_page.Rd
index 7da5acb05..35b1c3e9d 100644
--- a/man/tm_front_page.Rd
+++ b/man/tm_front_page.Rd
@@ -85,8 +85,8 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqX8opKAeNdqAfQ8vG3dPbyNdAHdaUgALFXYgqFxdECVdXUY4AEdBWiz2CDFSYmoiRkUIDIBBABEAZQAZH0y6pvTdT1JGdjbGlIUweC8kwdsIulFSdkHqwTjywd0AXl1BgDlnertdLhhBgbAk-1EiQUYCOCXVwdFWMli4TQJdUbBKgF9KgCsiFX8ANZwViiRJhcbGfhwExQYSkfwEfi0UQEfy-f5AkHAaDwUFJOQAXTcZCg9BE-gAjC0khgTMx4OwAJIQExEFa6AgzMDVA5rMAAITGKTscAAHqR2ZzZrzBoL3pUvGS4P4AEzUsK0+lwdgAAwAwkRqIIYFUKTrJVy9TKwLUhbp9YbjVUVebVpyAKwYd0pABsGB9chSDqNJt0AGZXRyuTy8Hy5XIFaTyWH1V5NbBtczWRbBq5Y4MAGJ2kXinNgADi1oAEmNKkpFeSVKh5i1JtMOoM7Em9BTrrtu5TcB2wF2lboVX2G8qVUOqnzRyJw5OB2GlHXoOgWioYjM50l2UlZxk+EIRKJ2SfhGJdxkMqQYP46SR4agoFIb7eMo8oFDGP5yKWbofp+GSDIyMCoOUXhkLoKisowMCeFYEB9mBEoEFAVQSGyjxZBgBwdCBfIAPJxDIsEsuUiGaCQqFgHqmG6Nhui4XA+FgIRt6Bpxd7dueqxTv4TbzEeIE-kiNHQAEXgSPxuhVnYACyjTRvwEnIdw8lKc05S6KI8QQKw-ayUxOEyHo+hMAAfEKPGmEQRCkBAjliGWAAadHIrsjymPkUz2Y5znkNaACasHnmRelwMQED8AFTkubZc6fvpRCRP4ww-mE7IOC4nGVBk3Fzt+v7sjJogACSxBSXL1LAqCLtU6B0BhklJRkrIuYwZVvpVqDRs1tCtch8UyEl660CYujsCo5DMJYOg2LYaRzvpKisE1-VoKgFV5Ck20VaIMg6BUSgfEoYAfASQA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_g_association.Rd b/man/tm_g_association.Rd
index 2509e026b..347744189 100644
--- a/man/tm_g_association.Rd
+++ b/man/tm_g_association.Rd
@@ -176,13 +176,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXVIhrqu-lCkULpwAB6wqCJKAUEGxlzUAPoxUDbRgcFGugDutKQAFirsKbi6IEq6uoxwAI6CtNXsPqKkxNREjIoQlQDCAPIATHG6-QMVpuqkHaLD0PCi7ABitNTkjOy0og4upVpokRyjpZsYJpMdpe0StATc7ACMADJyL129g8BnGtMAusPU+2ohw+XymjFEP1KUHEBHyLEmMi6AF8ukp9sMVHl2OMUroALz+DK4cZ8IQiGYE0nCMTY7qVXSkGCJCSJaGiIgEWiBKwQWn0+nVEz4wlBRJhUjMDSJUSoOAEPn8+kpOZ6AkKMCjdXEumK3SiOAiDTC-WG0jS2Xy8a6yoA+gG4XqgDKBrlpF0e0YXPoIkQWqt1thRBuYmFHq9IkSgeDCxSwGA6s1YB+kN0lrAAAUAWQtbp1XZWLKc3nqoF4NmwC9tdb6SbXXB+A6M1nSH6ddaTLRQvXhYsAIKPR2uNv8t6KuRVxUeikiqBi0ISybmuUK3XK2Cq3Mawat6u1o0EvdmmXL-26232tVgZ2m90scNiX14U+KqMEEMEsNQb1wSP5INvmMMjjBNtyTFM00zKBy1KPMCzgIswDsEtGQoFsK3HZ9+UPbtLyQuBS1Qndq10GBhE0SIN22ZwJ2rDsuwbAk+wHIdq1HEd-VHLouloIUNlUSVNB0GxbHKOlREKCBWF7dB2H2AASeooXQOT9UYHROiUJElDAJEfiAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXQGEAIgEkAZS9dfihSKF04AA9YVBElUPCDYy5qAH1EqBsEsIijXQB3WlIACxV2TNxdECVdXUY4AEdBWgb2CDFSYmoiRkUIOoBBHwCAGWT64bGlAF9+gCsiFTSAazhWUQrc23z+OBMoYVI0gn5aUQI0xeW1jeBoeE3MuQBdN2h0CZVi9lqQ3N0AF5-uFcH8+EIRKIgboIcIxL8BnVdKQYGkJGkoKJREQCLQwlYIIjkciGiYYZk0tFSMwNGlRKg4ARiSTkZkHnpgQowFNRtywUjWbpRHARBoYSKxccGUyWUK6tQoPRRTDuQFRUzSLotCx8fQRIh+X95boCCUlgQxDCdYw9SITubaJbNsaTSCoMBgNzedyXi8BW7kcy1c4ABr83TcrCDLyuPCRsBeADyjgAcg4AJoR71YACy2bAAQcgzsgwAjAWi9HSwAmAt+Ox2ABifPj3IAQrmsABpLB1sD9QNyANuyWauD8VVgaOxo2C+UmWhRCcwpuDUYBVzzkmD1nD111G3Q4GU6m06WM4Pbtm5DlTn14A-Isfi4Evi+yp8kxXK6hT9VStqupKlChqPteJJmhaVrAjadpwA60EuhBrKZJ63ojK2fojoGwaFmGBYznGVTcsmaaZgWgx5pWxalhWbaFrRgz9iRYANs2rasZ2PZ9tyu4mvuKF1O+K5cmA3G9ixX7IjARy0HEnL2E4zg4QuS6iboa4bluAlPvxui7v0-S0OS7AqOQ57aHANi2DUSKiGUECsIM6DsGgqAACQtFU7keSKjA6H0sxKGAMwvEAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_g_bivariate.Rd b/man/tm_g_bivariate.Rd
index ad90d451b..c8ad47e15 100644
--- a/man/tm_g_bivariate.Rd
+++ b/man/tm_g_bivariate.Rd
@@ -244,13 +244,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXVIhrqu-lCkULpwAB6wqCJKAUEGxlzUAPoxUDbRgcFGugDutKQAFirsKbi6IEq6uoxwAI6CtNXsPqKkxNREjIoQlQDCAPIATHH+GRgmzPDs-QNdAL5dSmiowyp57BUjsQC8m1C4G3xCIqK6O6QwiRKJ9NostIFw692VuqGnu4lhpMwaiaKocAITxeLxS0Hg7wUYGmUP2zxBojgIg070RyNIfwBQI2IMq1Cg9CRkLAAGUkYDSLotHcCSJELCcbiCPkiLQCGJ3tTGPd6CJEszWezRMUMsBgFCYWAALpSuRw3EvNEUuD8YnECwM+G4ky0UIq94AMQAggAZEmuLWVLoguWM1jvFKfULfdQY-6A4G4sGwPQ7CWDTUKpUonbBt1Yz0K-GEvx+0nklFcnl0wMK3QCtkcnZJ2lwfkszPClJi-0DKEy22WxUJ8iquOCVBBADWcFTCpgwk0kV9umNZuc8rTOr1dd7pvNjKtjMrIMYRGyiRM6jglJ2jq+P3DHsnu3BPdLber6NRNcx26reIJRLjZOPOd5cHpeB3lQzQs5NIf+cFYhFQRL0IBtKsqDkGNb6nGdisACh4gsOEFjv2O7Wi8M4vG0i7LquHwbq6Z7YlW3oQnGkqgUeFInui+GRri0bXroUK3hR94ps+F7pgW77Zp+fJvr+xbioBZbAWhYHoghUJ2NUgTwGQsEvPBo59hOVYoVOzxdF0tAmLo7AqOQm7aI8ci2OUzyiIUECsEa6DsEsAAk9SlA5iKMDonRKLMShgLMUpAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXQGEAIgEkAZS9dfihSKF04AA9YVBElUPCDYy5qAH1EqBsEsIijXQB3WlIACxV2TNxdECVdXUY4AEdBWgb2CDFSYmoiRkUIOoBBHwCAGWT64bGlAF9+gCsiFTSAazhWUQrc23z+OBMoYVI0gn5aUQI0xeW1jeBoeE3MuQBdN2h0CZVi9lqQ3N0AF5-uFcH8+EIRKIgbpSDA0hI0vRtCxaGE4L8BnVdFEYZk0tFSMwNGlRKg4ARMdjsZkHnpgQowFNRoywVjqaI4CINDDOdzjmSKVTqdjqFB6FyYYyAlyKaRdFpUeKRIhWX8RboCCUlgQxDDFYw0fQRCdtbRdU9csBgIzmYyXi85GyNXU+XK4PwpUyAOKuPDqkUmWhRD0wgBig1GAVc7Ox-WpToDrDxuQJUSJ6gF5MpAbqtNg9N0tpGLP9sddsp5wLdJMFOfLovFkoZYBl-IVSuNcFVZZdmrNFv1nZNWp1Yi24WtxemYAdiYbFf5oZb0YAGmqF7oYEdaHFCxGo85nS6gyHPcCD9Hc7p43Hj3VGEQCmkDrr5cD8YTiVmhdf8-AvTtXsRRrd9dFA0ls2FDUxQlagvTbOUO0NZVuw3PtR3NPVgQNI0RwHcdMinJkS3tR17xAytyHPIsmSwABZdCT2DZddEvGMNVvOp52pboX3UOAwM-dNv0g38G3-Qtp1LCjFyQ6sqLE+s+1g5taMQnlcNQntZOxTDBxw4c4FNMdLUnG0SJnOddLkjRWMZLwAHlHAAOQcABNJiNVPVj2OvLibz+fp+loExdHYFRyG-bQMTkWwaixUQyggVhBnQdg0FQAASFoqkyrLOUYHQ+lmJQwBmF4gA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_g_distribution.Rd b/man/tm_g_distribution.Rd
index 4bac76283..dfbc4292f 100644
--- a/man/tm_g_distribution.Rd
+++ b/man/tm_g_distribution.Rd
@@ -166,13 +166,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsBISqDC0ogT+uLpetHCk1Ky6ALz2Ts62AGTpuu7Rvv6B6BFR3rHxSSkuGVk53nkBRCbkoqRF0aUJyQ6VupnZnrVwfmAAsgCCAMrjrSVxHRVpPdX9PoP+TEREMNMxs+VdaUoAxLpSEGrUuvxQpFC6cAAesKgiSlc3BsZc1AD6b1A2r2utyMugA7rRSAALFTsP6REBKXS6HyhD7IxihJQAX0UECUaFQaJUEL8ECRf3KcMRuj4QhEonKdGapKRSNIMG+El+oVIGPogk01mprMuPO+WhYlKB3wevPUpG+olQcAILJFrL+0Hg5X8KNEEWF6tEcBEGnKxtNCqVKvYEoxUHoIm+BEhRFoBDEQz1-jkkX8AAVYtwMAAZCgSKE+w1I3Ei2O6XG42gmXTsFTkZiWHQ2WwIsm6UTQiCsUbodgEgAk3kileNjB0jFxWKUYCxAF0gA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsBISqDC0ogT+uLpetHCk1Ky6ALz2Ts62AGTpuu7Rvv6B6BFR3rHxSSkuGVk53nkBRCbkoqRF0aUJyQ6VupnZnrVwfmAAsgCCAMrjrSVxHRVpPdX9PoP+TEREMNMxs+VdaUoAxLoAwgAiAJLjJ7r8UKRQunAAHrCoIkp3DwbGXNQA+l8oDZPvdHkZdAB3WikAAWKnYQMiICUul0ozO4wAMj9shjsUoAL6KCAAKyIKn+AGs4KxRIiwbYIfw4CYoMJSP8CPxQgR-uTKTS6cBoPB6UC5ABdJRKLQsUQARlxBFhFIIYn+ojgIg0cH4fggaLljFoUHoIi5qto6vFYOAwH8+Kx-klksiBCGoywwyK-hOAHlHAA5BwATV9YHGzgAGv45HJcKjdFqdeR+OUg44sc6ICSlGhULiVDCDWigeUkUm+EIRKJytXhGJS2jdKQYP8JIDQqQTfRBJprEmW7du-9jRWwf8Xj31JzRKg4B6h8PbmDRXpko7Mc68MvhynF6RygeNJqF0vDSvhyq1WJysbTea4Jbb7aHvatwSwK73Z6AOKuHguj+AAQsMWAANJYAqcYJnuK4nmm5SgeBUEwbul5XmiMAcrQ7wbroABioxYlGiaYVhJi0M8erlMRpGuBRw4klecFMcmM4PGOLATlx07MKe86Ls2V5AuuyFgE6ETwWiVHUOQjDlHJClnsJMktsadbJJpCrkVhLY4fJeEiHsqTqSxK5sVeEiMEQgioNxinJECU7PDOgnniJK5ibABGfjuemUbQ8kyEpwUqUJF76Ua8r3vKunqdhuH4aZLjmfBFlohZJIkrQJi6OwKgKbO2iDPGugopeojwhArCjOg7AFgAJN4kTNVqjA6IwJKEkoYCEpKQA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_g_response.Rd b/man/tm_g_response.Rd
index 478e393a2..4dd5e9d33 100644
--- a/man/tm_g_response.Rd
+++ b/man/tm_g_response.Rd
@@ -200,13 +200,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXVIhrqu-lCkULpwAB6wqCJKAUEGxlzUAPoxUDbRgcFGugDutKQAFirsKbi6IEq6uoxwAI6CtNXsPqKkxNREjIoQlTCtLKJxur0E-RWmHbrsWroqugTsCoSs1Iuli1qiq7qLsFuLUiyLcrbl3ZVDfYyiwMBaALp3g1DiJuqkHezD-Tf3d12VAF8lACuko0KhBio8gszildABefwZXBjPhCEQDRFo4RiGHnXSkGCJCSJaqiVAkURwPH43TUKD0OB+RGLLBiCkQKm6AAK7VImzwY3xZI5XMRKUSYVIzA0iXJcHmQtpKWg8AR2zAXyuqyV+KpIg06v1CtIctQCpptPO9MZzI1AGUmSbdFoWLQGSJEDqzlbKgR8kRaAQxOrXYx3fQRIl-YHg6JihkbostQKHqVFUsVngNQdGEc5Cifb7jRo4Px1YsCMtvb7zjBhJpInpEQAxACCABl7c5C7XKiZaKEy+r213XEX8f9aQXdbpQuqJVKZab5YqJ+cVbBmxqUzXi07DYiSyvzWu+3SGUyK2BHQbSC63R64F7Bev8TGgyHEWGI1GP3GEyCJNNUuVM7nTBYwA2PYUBgfNez7Y9hxZKCBQQ2t62oRsRBHTtu3Q30ByHctWzw8daynSclSnLouloExJhUchl20aljjKMZREKCBWDbdB2HBAASepSiEqlGB0TpgSUMAATuIA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXQGEAIgEkAZS9dfihSKF04AA9YVBElUPCDYy5qAH1EqBsEsIijXQB3WlIACxV2TNxdECVdXUY4AEdBWgb2CDFSYmoiRkUIOoBBHwCAGWT64bGlAF9+gCsiFTSAazhWUQrc23z+OBMoYVI0gn5aUQI0xeW1jeBoeE3MuQBdN2h0CZVi9lqQ3N0AF5-uFcH8+EIRKIgboIcIxL8BnVdKQYGkJGkGqJUCRRHBEcjkdQoPQ4NQYQowFgxDiIHjdAAFHqkUSUsFIwlY2n04GZNLRUjMDRpbFwAgEwnIzIPPTAylTUZsv6S3R4kQaGFqsXHUXi5Uq3TE0nkuVgAJk7W6LQsWgkkSIJUcg0EEpLAhiGHWxi2+giE6u2jup65YDAeUjRVgF4vKp6sAAIQAslgANJYABMbN0lK8AHlHAA5BwATUpcjk7INyK1Gjg-ApCeTaczeH1KpgR1ocVlugAYoNRgFnJWq6ZaFE6zD+4PXE7Cf0VRW27oojC+QKhTrUGKJSrpbAe+Hpq259WLRrgTWtzvl4SjWSG+b1aQrTa7XAHSfR7oXW6PcCvR9P1f0DBFMlDI9I2jWNfjNZwAA0s0pLBBi8VwwHLEcqyvSdTRQtDHW-DtqE0bspwHIcsINExx1wvsKNnKsF0lZi6mY-p+loExdHYFRyE3bR8XLao-lEMoIFYQZ0HYNBUAAEhaKpZLkvFGB0PpZiUMAZheIA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_g_scatterplot.Rd b/man/tm_g_scatterplot.Rd
index 9f03f48db..43439b489 100644
--- a/man/tm_g_scatterplot.Rd
+++ b/man/tm_g_scatterplot.Rd
@@ -296,13 +296,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsBISqDC0ogT+uLpetHCk1Ky6ALz2Ts62AGTpuu7Rvv6BzgAepMwRUd6x8UkpLhlZOd55hETURIKMqLQEANYyZdGVCckOtUoAxLpSEGrUuvxQpFC6cIWwqCJK84sGxlzUAPpbUDabC0tGugDutKQAFirsR5EgSrrZno1w7NOipMStjEUEDeAGEAPIAJh2unBEKUAF8gUo0KhoSobn5gXMztUnq9dHwhCJRNVCcIxJi3m9SDB9hJ9mEFuQOq1SJSqW9qFB6HBZsl-ABlAhMmTrIikGG3IhdMQRfEcwq4s77FYldSkBmoOAEdkct5HaDwar+WFyrF63SiXnaiXJK0iDSa7W6i26Lk8vm6QXWjS6LQsWjckSIM2uqkEKUyknJf2MQP0ET7CPSggUo7AYAmyH+AC6OciOv8xAsZX8glQi16-jkclw8td9ptcH4xuaJbw9YtMGEmnWemSADEAIIAGQFzjr5tdJlohWb1WHY9cU45QIttc7uiG2MWKuKzEdoi1hZXVINsH7XrApo7p7ejd9dp9GqPzs3HPdvNbAuffoDQbgENbzDN5kyjapY3jRMwNTURHjODMszhMA8wLPw23CPAr3LSs4GrDc7ypB9yBbfkwBwqAq2AkDu2oXsRAXUdx0nEDTFnedByY5cwzXPUCItf4iEYfZ6G3I49zVQ9jxdDlzyNMibxYhtfyfB0X2k98qU-T1vTUv84wAoClLDGCxAg-8EzgJNI1gmTXXTTNr2zFD800jlCzAAAFLkyFLMA7FYLU-LsdwFngXysKLEhMMiMsK0ovCwF4njjOUtSON0AA5RwRxHVKux7Wg+0Ypd8r1Gc51I3RF3HTTkqpfi9VEWgAC8rNEpVd1VA91LfQi5MvJDQzSm1qmIp0T1Y7Tv1-SDDOGkybLMmMLOgpa4IcoaXLQqL21i8j4qomsyo5YiMri3CFtdWj6MvGqJzctjKpK2rCPqt5Go5RgiEufYTHUWJOqgCSeomuz9TOQ1Bqc5CTstFT4bUsHHumsifz0ubLKMx7TOjfSoKs3H4MWRCYdzfNdA87yoAi-aAqCyL-NCmkKFIfC4fvZ8Muy3KOYJQris40rHoqjL7rqzdPvDFo-oB20d2B7r1WR-rIYvVtFM04ixufFWpu5L80dm1bAKugT1vMgzLOslM0wQxyb1Qyn0Op2mr3pxK6eZ8K2aSqWLTOqqebyx6bqKhiheYkX2Kq8W3sl+teKBIFaBMXR2BUZl1W0L4a10F4sVEe4IFYId0HYFEABJvEiKurUYHRAQRJQwHhHMgA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsBISqDC0ogT+uLpetHCk1Ky6ALz2Ts62AGTpuu7Rvv6BzgAepMwRUd6x8UkpLhlZOd55hETURIKMqLQEANYyZdGVCckOtUoAxLoAwgAiAJIAypO6-FCkULpwhbCoIkorawbGXNQA+vtQNnur60a6AO60pAAWKuznkSBKutmejXDsEDEpGIrUYigg3wAgtN5gAZQ7ZaFwpQAX3BACsiCoTr1WKI3tdbLd+HATFBhKQTgR+KECCdMdjcaJgNB4PjznIALpKJRoVAIlSPPwQ5bXarvL66PhCESiarS4RiYXfb6kGAnCQnMKrcgdVqkZUq77UKD0ODUar+eYEHUyHZEUhTJ5YghiCKSo2FcXXE6bErqSmiVBwAiGo3fc6svTJfxI2HukXh3Sic0hx3JFMiDRa4Ohj1J3Qms0WmNgeapjS6LQsWimkSIBMFlUEZ1dMTVauMWv0ERU1uu9nXYDAWMw+NgTmcyJ5sCQgDirjwun8ACEALJYADSWAAjGVVxvtwAmfxyOS4fNJzNpuD8S2zheNptSim0HbR3QAMUhsPmzgviYFiYtCFLe1Tfr+riAUa4JJuel66EMoprL6xTMNmQYhmG4aRrAH6jsieAId816VhmFaBrm2FJkW5r3uWWaOp23b1k+TYti67bJMxdZwH2nGDmsw4EeOk7Tn4D6LpEB5bru+5gOusknmAZ4Ac+yYUWBpaKdue5EdB4YwK+77gT+f5qc+wGgXeyQQX+xG6LB4bwQZIJEIwJz0Eh5yof6GFUQ5uHwPecZseGpHphpjE5lhDnGqadGlgxaZVjWvENvp6kcW2crcWlPZ8dlA7UQW5zCbOY7+GJcXNhJ85ScuCmHnJS4yce8lYJCkwNf4WDOHOswAPIAHJ6U5TYuepEVabow2OLCsIWU2RnUJoJm2WZ-41VZM12VBE0IZN4W0AAXnxXneihfroZRsUGRG1xRiFlWZQWEXVBFMV5vdKq0SWjXJZWPEFRlS0FkVXGpV2vH8TlBJCSOFWEWJugzvV8k6S1qk1dNNmNejr3LcZIimZBYNJjteN7Q540qkdRqMEQdwnGSrqRT510Bl9JUPWsT2lqFhPhRRH0UdzNV-fRIvA6xQtJhDuVQyxhX9kqZWI4LKMzpjynSWAnXdR1-VDaNp7029ml43NC3k4ZxMfntttGpTpP2T9tPfOb3wgiz6ixJdUC+Td4s-UF+FI+OTtRSl5HRZh33qZLSXS-lstR97quKzLKsCfDUDlZrU6oxJOsdV1PX68bI1jV7wuMTN1uLTVK1rSTG1k9tIG7ZtNOHfmTnguCtAmLo7AqLqAbaP8Z66J8IqiC8ECsJC6DsHyAAk3iRBvKaMDoYKokoYAopyQA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_g_scatterplotmatrix.Rd b/man/tm_g_scatterplotmatrix.Rd
index 7faa664d1..7a9cb9c0e 100644
--- a/man/tm_g_scatterplotmatrix.Rd
+++ b/man/tm_g_scatterplotmatrix.Rd
@@ -204,13 +204,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CmlCkmgRw-ri6XrRwpNSsugC89k7OihAAxLpSEGrUuvyBULpwAB6wqCJK+aSFRrpc1AD6VVA2lQUGxgDutKQAFirszeEgSrq6xOakjFGiHXkFGCbM8H4QY2O0-AnjfmAAIq54uv4AYlhhx2AAknYX-s4AyndgAAq3R-4A4ucfYAByABlngAhQ7hfwAxzPACC7zkuFG6wkRB0jAg8DI2xM6lIREYq3W6wI7AATOEyboKQBGcm03Q0+nhBkk+GIwnUKD0ODUWaJYn+ACyJBYBF6rGeWDgqEE9DoBH8qUJrLW6w5EAkgigUga2JgtFiWJxeIJhJ2DIAzOFLbprdbqUyrUzlabdByuTztvywJ8ZDAoMp5b8ABLckQBiVEP0WUJgRXrZ3rVBEaUczQkT3sAAc1oAbAB2cI5gAM4QALAX6SX6QyqRWqQyixgc+EAJwJsYsOCFPnsc0AVgrfb7FqLDL7Rb7rep5oppZH5Kb4Wz7cy-FQGfNGFLC4rJIwNa34Ub1sbFMbFcbk90jYbW5X-Dg9FIGb3zIwdsPlMXX4-25-C7-PdfzjONRG4MQ5maRZljgE0Ni2RIqUQccERVMYJjINgGk2bYwJgcpYLZIldgOZ4zmeG5nkeZ43meb5nkBEEwUuSEYThVCXVEWgAC89ESFCiLGdxynUPikhcIiV1YLtGFwvFSHYPCCNJUci0QEkiw08IUN0YSORCbYHBcOQVx0CBBDEpSRHYL1RD9ahqGeeB+FoQQYGeDlGCkZ4SDobIFW0qs9NEwzkhXAh-RCBy4AQ3QrNg4kjOccITmhAEHhSQLwmCgzEiSlcvH9TRSDiRI0TxGB2B0qkiyrDTwqIURSF5XSIAqqqq0zOqixXVBGCIEwem2crGEqnStMrEClAAX1SAArIgVAaABrOBWFEQYClsWoFqW1b1pNXaIBWtbdgwqYZmec7pjEZ5NgCxEjpOjh-DAkRRGeN7bt+e7Yw43Qnv2s6iEmG6Pt+L7wfCL1fu2fxrtYbD+AVVJUiUNB11qFQehNZptiGRE+CEd7tiJ4QxDguoYAaCQGlECKghkcoiFIP0LuKSmxjdbk4bAB4GfIRhmefNnpmKMJBN0LQWFoTkScSOgms59ZmgaEophxOnUDgfk0JdeZqmgeBeeuy68ElwlRG5HXn0SK2RA0LWdeVl1udyRJ-Aea2NClmW5bERAJb1-Xxl6RaQha6Xpn9hpRXDinmmAYB4ZBzCzYAXXTlcQ-tm2YozfxOygZ4JDXZ4HyfB7g-1mBhE0AjQpcf6Q7GPEH3cWKkublvBuKfPElS9LXGrpULd0bOVYKNXig1x3RG13WW4N-1YDE17wKhsexkG6hBaxfVBadxel9dTkeY9vnvefKPZdlOBA-NkfTSjlqU9BxHfu7kO49oCPtml6gFlY5h1-gnAoSd17vX8JncEhBU5TA-sjP6W91i5w0P3HY-hSK-HIr8SivxqK-For8eivxGK-FBM8VivxYRVxProWuu9aANzyskFBE9LZX1wlfI+LtTRu15l7B218-Z31EA-L++sf5-0SDfGO0iwHVAgWASG0D07Q12IVMgPRxS-GIE1KGlw+oDR6CjSRnEr4YK9Fo4qujYH6Oas8Yxg1SB0JPow+uIhG7JRQa3Rg7cMFd18aYWgfdYqDwyuwsecZR56ymhAVItATC6HYCoQWOJtCwRMroEYKpRD9AgKwaE6B2AYwACTeHCOUq2jBUSpGmkoMA0105AA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CmlCkmgRw-ri6XrRwpNSsugC89k7OihAAxLoAwgAiAJIAypm6-IFQunAAHrCoIkolpGVGulzUAPr1UDZ1pQbGAO60pAAWKuwd4SBKuroAgtn5ADK9uoxzi1Oz2Vj5y6tb+UoAvqkAVkQqrQDWcKyiY6W2TfxwJlDCpK0E-LSiBK1nF2ut2A0Hgdw6cgAukolGhUMsVIM-BBph0EsVSrgNnwhCJROiccIxMjptNSDBWhJWr9AuRGDUiOTAoxaBUSaTptQoPQ4NR0f58gRaTIGaRdDBmaywhsOVoWLRuXj0XRRKR2RzUaVWpVSMwNNTUHACOqNZqGqC9Il-GsFtKUabSaJeUaxYknSJ9aJDcaZQ7OdzefywPlnRpdHKWYqxIg7X6OQQhucQvjEhGFfQRJ9E7Rk-cGsBgNb5rawJDIXIsfa47p3S64Px0T6wDMAOKuPC6fxYGaZdvhAXOAAa-grvr9MHetBqlqSLkr1emREYz3cDcSDjnY4dJlZ9fRADEZgt8q4qw7Un7R2eOR1tRVdeoPl6jSbTR0LUG5ttY3Gd9Q6eif50gaL5bqaXI8nyVrBqGYoUPwqDnGQogxngYEahGKa6E2AAKMzdgAsjkYSds2ABqBS5HYI7zguCZJmI6JytQghwFmDHgqUBZFt+paQuEuH4TMRHZCR1oUfkVE0dhfhgHhhFieRlHUWAchXguNawXu0G5AAcmRzh2LoxjOLp2S6AA8vuuh6dkjiZHYuQWbpP7VhO-5TiI6Ibqe1bqXGtZhm6sEgT614OhBgbQSGHpimmUYoa5cb0TmjGpvKUbsalnH5oWzb7P4Zb+dWgXkGuMnWm2ikzGRR7VdkACaNHoRy7maNO3nJLR1ZLiu2mzs43W-ru5WHsevlxhe55blN0xTakqS0CYujsCodKPtocA2LYkz2qIIwQKwMzoOwcIACTeOE51OowOiMKkhxKGAhyQkAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_missing_data.Rd b/man/tm_missing_data.Rd
index 42a0303c7..d5b1e919b 100644
--- a/man/tm_missing_data.Rd
+++ b/man/tm_missing_data.Rd
@@ -14,7 +14,8 @@ tm_missing_data(
list(caption = NULL)), `Combinations Main` = teal.widgets::ggplot2_args(labs =
list(title = NULL))),
pre_output = NULL,
- post_output = NULL
+ post_output = NULL,
+ decorators = NULL
)
}
\arguments{
@@ -47,6 +48,9 @@ with text placed before the output to put the output into context. For example a
\item{post_output}{(\code{shiny.tag}) optional, text or UI element to be displayed after the module's output,
adding context or further instructions. Elements like \code{shiny::helpText()} are useful.}
+
+\item{decorators}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} (\code{list} of \code{teal_transform_module} or \code{NULL}) optional,
+if not \code{NULL}, decorator for tables or plots included in the module.}
}
\value{
Object of class \code{teal_module} to be used in \code{teal} applications.
@@ -57,6 +61,21 @@ gain insights into the completeness of their data.
It is useful for clinical data analysis within the context of \code{CDISC} standards and
adaptable for general data analysis purposes.
}
+\section{Decorating \code{tm_missing_data}}{
+
+
+This module generates the following objects, which can be modified in place using decorators:
+\itemize{
+\item \code{summary_plot} (\verb{ggplot2 plot grob})
+\item \code{combination_plot} (\verb{ggplot2 plot grob})
+\item \code{by_subject_plot} (\code{ggplot2})
+\item \code{table} (\code{\link[DT:datatable]{DT::datatable()}})
+}
+
+For additional details and examples of decorators, refer to the vignette
+\code{vignette("decorate-modules-output", package = "teal")} or the \code{\link[=teal_transform_module]{teal_transform_module()}} documentation.
+}
+
\examples{
\dontshow{if (require("gridExtra", quietly = TRUE) && require("rlang", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
# general example data
@@ -113,13 +132,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsBKMtPzOAB6kzP64ul60cKTUrLoAvPZOzrYAZJm67rG+-ozUUBASUTHe8YkpaS6KEADEulIQatS6cKGwqCK6-FCkUEr9gwbGXNQA+iNQNsMDUGO6AO60pAAWKuwz0SBKurme3r6toqTE1ESM9fu6UPz8k9CiS2YWmtahtnsQBwehwFE3RE7FEnkm3BIEnYX2iJkuV3YIlKGxhtgAVLlzLQTOwAIzRDAABgArIS8QB2OTUgC6SwAcgBBW7-W4AXyUtx8tBeRl03NEtxg5xYvOMwoIos5v35QVEwDpfOK6ES7AF0Xuj2e9QOEtFCqWyp6HD1jFEGoeTygoh1ulN8uA-gIrGo-hpiuM1owJnUpER9uAjsILrdNNtAaDUhYoaWXp9Gn9IrNgf8UcYofqbJu0HQSxUaz8MpmNR2QoEwjENT4QhEokLf10pBgkxgPNEKgk0wWcxl9XqON0atUzEsOhs31uok2EFYjPQ7DQqAAJN4Negl2DGDprkoORAwGyaUA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsBKMtPzOAB6kzP64ul60cKTUrLoAvPZOzrYAZJm67rG+-ozUUBASUTHe8YkpaS6KEADEugDCACIAkgDKzbpwobCoIrr8UKRQSiNjBsZc1AD6k1A2E6NQ07oA7rSkABYq7IvRIEq6uZ7evhBipMTURIz1pwCCrZ0AMuuML+8nui9YnU+-06SgAvvUAFZEFRzADWcFYogOq1sRmGcBMUGEpDmBH4tFEBDmUJh8MRwGg8CRizkAF0lEo0Kh1iptn4IKdFjVDr8+EIRKIanzhGJ2adTqQYHMYATRCoJAtVssObp6vVaCZdOwVORmJYdDZbMcVaI9hBWE90OwmQASbzRW2iGQ6B5gpRgUG0oA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_outliers.Rd b/man/tm_outliers.Rd
index 194a8f14f..ff738de8d 100644
--- a/man/tm_outliers.Rd
+++ b/man/tm_outliers.Rd
@@ -151,13 +151,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXVIhrqu-lCkULpwAB6wqCJKAUEGxlzUAPoxUDbRgcFGugDutKQAFirsKbi6IEq6ugDCAPIATHHV9RVNdcDACmCojLQwLKyJANZwrJ0AumONonAAjokiEOwQjETZ7LV1cooQAL7bAFZEKkMjosUZtlmHx8OsZ9cQJxydG52lL814up3dvf1PnS2bggWhYokaBHyRwIYkS0xEGjg-HYoJ6UHoIkSkOhYnOQXaHzq4zGpQI7E6AAVqFAyG9vmA7KxUHA6Z07Iw4IF4LSwFttko0KhGio8uSIJUUroALz+DK4Fp8IQicEyxXCXEtSqkGCJIiCUh0GRnTWVXR6g20GSJVHS3R0USkMWm52yoKJMKkZgaOHMskml2ummwPQywlvf0u+FwDS2qPe0S+p0Bl3U+hwPyhsAAZXT0dIulRtHRIkQ4fFyed2NoMJVBZYRYxcCxUOruJSBLArzAE1J5MIJAIrLAglQQWGgLk8vLFcqcfI-FtnRHY5ZeAjAZgwk0kRDugAYgBBAAyWecU5nppMtFCSNth5Prmnye2FZfLsnEYIgTgEiIPS-SQ2jK9qOuugbuqEnrqKQPrRkmFYpNA8CLp2nznjOV7UOQjC2ph2GwX6T4VqitYkehF5VjWtqgtQghNpRbYZB2XY9nWjCiAAJHOSIfkRybcQuMo0XRzY4mc7YdKhRLdiSbGcQJvEXpUm5YbQO62g4LhgZUb4Brppr6W+2zbLQJi6OwKjYdB2hwDYtjlOWoiFBArAHug7CChxgi0KUnnTIwOiMNsOxKGAOxjEAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAokqUBiXQGEAIgEkAZS9dfihSKF04AA9YVBElUPCDYy5qAH1EqBsEsIijXQB3WlIACxV2TNxdECVdXQBBHwCAGWTdRkaWpQBfRQgAKyIVNIBrOFZRCtzbfP44EyhhUjSCflpRAjTB4bGJ4Gh4Scy5AF03CAWNNK0WUTSoflFqNoOxdgAxWmpyRnZ1hxcVVEaDiHEywGACjAnWaUJOJyq6wwl1IREYcgxShujFEbQIJSGBDEaVEcBEGjg-HY2NoUHoIhWBNoRKOuQhUJhcIRpnUy2xdweT0xECUILaKmK7FqIVyugAvDLwrhpXwhCJcQrVcI3tK6qQYGkiIJSHQZJNdXVdEaTbQZNcWPLdHRRKQpRBLR7FVA0tFSMwrqJUHACG7PZ7Mq9HRymrC8Baw6TyaRHYng8tA8HQ2HPdQ6WSo2AAmS07oaXSRIgocr3dmPfjCWJHWX6XBGQ3WeF2dCY1yqiGOQBxVx4XRQgBCAFksABpLAARihGOrtY9qYp-AL9SHVfj2ZgS1ocT0Cve9WaAWcy5XdRMtCilMdp-Prhrtb6b93civdbCcAkaOZbh7UYR1nVdXc6kyH0oj9XkSSDftX2zCNYGPUduy6OMkLDW9vhkR1cJ+eDMwgz1+SbW5vxXetmUbBUbmoQRWxolkpk7SEMNjeEqn5AASNdyH4L9SNXYt1woxjmKZVjwQ4zkwG40tbn4sTBOE7C9wPI9HQBF9r3fbMDI9IzdAMvo+loExdD+VR-U0HQbFsGoa1EMoIFYep0HYEFeMEWgqh80lGB0dEeiUMBuhOIA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_t_crosstable.Rd b/man/tm_t_crosstable.Rd
index f4e4953e9..23ef6d6e2 100644
--- a/man/tm_t_crosstable.Rd
+++ b/man/tm_t_crosstable.Rd
@@ -175,13 +175,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsIykUPQiov64ul60cKTUrLoAvPZOzooQAMS6UhBq1Lr8UEG6cAAesKgiSgVFRrpc1AD61VA2VYVQBsYA7rSkABYq7M0RIEq6ujCkBCyinRNTM2OmRIy67Fq6KroEfoSs1OG6-lpheEcoMIf+Uiz+crajEOPjk9OMosDAWgC633NQ4hM6lIK3Yrxmnx+3zS4wAvktwe9Pv5UIxaDAWKwGgBrOCsfy-OaiTwNEQQdgQRhELpghbve5KWFpABWRBUOLxoiG7VstVZ7NxrC5-IgHI4-kRpwiErpUvOqPRmLFdzSSjQqDmKl6fie+XaiT1QVwCIEwjEBr4QlCOuedRgDVIDQIVNEoiCITgNttumowTgeSS-gAwi7ZnZgpU8EtbSUDc0GqVSMwNA1RKg4Dto97mtB4AaZW8pVnbcSRBoDaWM460xmvd7nr76P782AAMr+qu6LQsWgRuCIcLF70EPpsgjmpLdtF9p2j2jjrnNZFgSUE74RTN7A5nY5y-ywK5gG6MFXG3X18aVjRwfgGzcEfaH493M8X54wYSaCp6JIOFyvt9dBWfgZBvA0-2cAC3xMWgSjApIADEAEEABlW1cc9vRhLCoOeeIknjRNk2rdNM0w20c1gH9zlXKNyOeK9SArDsUxrMjAJ9P0A3OdsyyYqdew9Ac6I4kcxwnLsexnMT5zEbkgmXWjfg3XYH23aUwBOQ8Dx3I84FuMB7lw+tGPg84tJEwCP2oL8RANZC0MgodbRguDb0Q1D0Oc3RsNtXyfKWNI0loEw1hUchiO0T17l0R5LwGCBWCQ9B2HVAASbwInS4lGB0Rg0nhCAwFhb4gA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsIykUPQiov64ul60cKTUrLoAvPZOzooQAMS6AMIAIgCSAMpZuvxQQbpwAB6wqCJKpeVGulzUAPoNUDb1ZVAGxgDutKQAFirsHREgSrq6AII5BQAyfbqM80tKAL5pAFZEKq0A1nCsouM9tk38cCZQwqStBPy0ogStewfHp8DQ8GcdcgAukolGhUCsVEM-BAZh1EiUerhpro+EJQvDUcIxNCZjNSDBWg8CIwiKJREEQnAcbiZtRgnBqPD-FkSWT7ME6nhkTTKvCOq0qqRmBpWqJUHACNSabCer89El-OtFuFudLRAyJaR4eqRCKxRKpdLafTGQqwAUNRpdFoWLQOXBECqYUbcQRhvsCGJ4TbGHbKY93bRPf8esBgIqFsqwIDARFRIJ6OqtUkzBZNNYAbops6XbjaPxeU0AIQ29Bxc5BCIqYYyIaiCLUIgSIPcdgARjkEUl-hyZTg4V0-gACgB5Ap5AAaGgHw7Hk+opH8cjSuZp7lIgkYEHYcpDQTkwHzlUBK9X2yROZdOs1cH4TLAWRHjgAcg4AJpO1co+60Wry5IuBeX5EIw1zuHeSQOIBqpGiYtCVLe8IAGKzIsBSuJeNKnlhQHSvEST8oKwoPPq3aYbiHRyveSqflelrJro156uKZFfnS9AMveFq6lqPp+iIjpcuRNJuh6XpJHx9oBmJe5QGGEYbNGsaMQmSbwqmlgZhcWYwS6R4rKWtQcBMugvBgtwaCBDZNi21DtsuulGuum7bruFZQAeR4no5uLnj5MxMeQEGDuazgTrRuYwD+f7Iah6G4bmcEIcFKFoRhubYbimWnmkaS0CYujsCo5DEdoVLLjpzqiKMECsLM6DsGCAAk3gRM16qMDojBpJsShgJsgJAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}
diff --git a/man/tm_variable_browser.Rd b/man/tm_variable_browser.Rd
index 752c4c83d..b36911ed4 100644
--- a/man/tm_variable_browser.Rd
+++ b/man/tm_variable_browser.Rd
@@ -104,13 +104,13 @@ if (interactive()) {
\describe{
\item{example-1}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsKKoLADWdBBw-ri6XrRwpNSsugC89k7OtgBkGbruMb7+ABakMNQA7rT8UqSikdHecQnJqS6Z2bne+WAAVqIkdOS1MQ2JKQ4tSgDEulLhsrr8UKRQunAAHrCoIkoLSwbGXNQA+jtQNtuLy0a65aQFKuwnUSBKuro+tKJ7b4wfL7owpAILE+VwBQMYNQgr1KRHgUKuMLhfxMUFotzM1C+KLRBQxfwAwgB5ABMXyJxKUAF9FBAlGhUF8VGi-FD5hcmo8-nwhCJPilucIxCzXq9ioctCxaFB6CJDkwiKVRDJhSLXtRpXBMSl-AA1SXSkS6eWKmT+P6vGkWpQ02gmXTsFTkZiWHQ2WzPVmiO4QVgAQXQ7HpABJvFFg0rGDpGDTKUowJSALpAA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
\item{example-2}{
\href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqajGIgEwCu1OAGcMAcwpxm1AJQAdCLTIyoBUrQBucAAQAeALS6AZoIgbaJdnN0AVLAFUAoksZwAjoNrv2CsKKoLADWdBBw-ri6XrRwpNSsugC89k7OtgBkGbruMb7+ABakMNQA7rT8UqSikdHecQnJqS6Z2bne+WAAVqIkdOS1MQ2JKQ4tSgDEugDCACIAkgDK07pwAB6wqCK6-FCkUEp0TCwcgSFhcIoQu-sGxlzUAPo3UDZKL3e65aQFKuwvURASl0ugAgrNFgAZT6McFQ4Fg2Z2OzOGHg5GuCAAXyuXSIKkewTgrFE-z2UFsRh2cBMUGEpEeBH4tFEBEeeIJRJJwGg8FJLzkAF0lEo0KhPipaKQ-BAQR8UgCEXwhCJRE1lcIxDKQSDio8tCxaFB6CJHkwiKVRDJtTqQdRjXBqE1-AA1Q3G7bmy0yfwIkFXf1KK60Ey6dgqcjMSw6Gy2IGy3SiX4QVig9DsMUAEm8USzVsYOkYVyxSjAWMFQA}{Open in Shinylive}
- \if{html}{\out{}}
- \if{html}{\out{}}
+ \if{html}{\out{}}
+ \if{html}{\out{}}
}
}
}