Skip to content

Commit 3cd6c50

Browse files
add option to remove empty columns in tm_t_crosstable (#890)
Closes insightsengineering/coredev-tasks#363 ```R devtools::load_all("teal.code") devtools::load_all("teal.data") devtools::load_all("teal.reporter") devtools::load_all("teal.logger") devtools::load_all("teal.transform") devtools::load_all("teal.widgets") devtools::load_all("teal") devtools::load_all("teal.modules.general") data <- teal_data() data <- within(data, { mtcars <- mtcars for (v in c("cyl", "vs", "am", "gear")) { mtcars[[v]] <- as.factor(mtcars[[v]]) } mtcars[["primary_key"]] <- seq_len(nrow(mtcars)) }) join_keys(data) <- join_keys(join_key("mtcars", "mtcars", "primary_key")) app <- init( data = data, modules = modules( tm_t_crosstable( label = "Cross Table", x = data_extract_spec( dataname = "mtcars", select = select_spec( label = "Select variable:", choices = variable_choices(data[["mtcars"]], c("cyl", "vs", "am", "gear")), selected = c("cyl", "gear"), multiple = TRUE, ordered = TRUE, fixed = FALSE ) ), y = data_extract_spec( dataname = "mtcars", select = select_spec( label = "Select variable:", choices = variable_choices(data[["mtcars"]], c("cyl", "vs", "am", "gear")), selected = "vs", multiple = FALSE, fixed = FALSE ) ) ) ) ) if (interactive()) { shinyApp(app$ui, app$server) } ``` ![1](https://github.com/user-attachments/assets/bea60bc5-e00b-413d-a4e2-ca29b45889eb) ![2](https://github.com/user-attachments/assets/e82dd054-fb72-459a-abad-9f96b724d3b2) --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 72afb30 commit 3cd6c50

File tree

3 files changed

+63
-11
lines changed

3 files changed

+63
-11
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
### Bug fixes
66
* Fixes output is not updated when filter is added for the modules: `tm_a_pca`, `tm_a_regression`, `tm_g_scatterplot`, `tm_g_association`, `tm_g_bivariate`, `tm_g_distribution`, `tm_g_response`, `tm_t_crosstable` (#870)
77

8+
### Enhancements
9+
* Added `remove_zero_columns` to `tm_t_crosstable` to add an option to remove empty columns (#890)
10+
811
# teal.modules.general 0.4.0
912

1013
### Enhancements

R/tm_t_crosstable.R

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,23 @@
1919
#' @param show_total (`logical(1)`)
2020
#' Indicates whether to show total column.
2121
#' Defaults to `TRUE`.
22+
#' @param remove_zero_columns (`logical(1)`)
23+
#' Indicates whether to remove columns that contain only zeros from the output table.
24+
#' Defaults to `FALSE`.
2225
#'
2326
#' @note For more examples, please see the vignette "Using cross table" via
2427
#' `vignette("using-cross-table", package = "teal.modules.general")`.
2528
#'
2629
#' @inherit shared_params return
2730
#'
31+
#' @section Table Settings:
32+
#' The module provides several table settings that can be adjusted:
33+
#' \itemize{
34+
#' \item \code{Show column percentage}: Shows column percentages when enabled
35+
#' \item \code{Show total column}: Shows a total column when enabled
36+
#' \item \code{Remove zero-only columns}: Removes columns that contain only zeros from the output table
37+
#' }
38+
#'
2839
#' @section Decorating Module:
2940
#'
3041
#' This module generates the following objects, which can be modified in place using decorators:
@@ -155,6 +166,7 @@ tm_t_crosstable <- function(label = "Cross Table",
155166
y,
156167
show_percentage = TRUE,
157168
show_total = TRUE,
169+
remove_zero_columns = FALSE,
158170
pre_output = NULL,
159171
post_output = NULL,
160172
basic_table_args = teal.widgets::basic_table_args(),
@@ -175,6 +187,7 @@ tm_t_crosstable <- function(label = "Cross Table",
175187

176188
checkmate::assert_flag(show_percentage)
177189
checkmate::assert_flag(show_total)
190+
checkmate::assert_flag(remove_zero_columns)
178191
checkmate::assert_multi_class(pre_output, c("shiny.tag", "shiny.tag.list", "html"), null.ok = TRUE)
179192
checkmate::assert_multi_class(post_output, c("shiny.tag", "shiny.tag.list", "html"), null.ok = TRUE)
180193
checkmate::assert_class(basic_table_args, classes = "basic_table_args")
@@ -189,6 +202,7 @@ tm_t_crosstable <- function(label = "Cross Table",
189202
label = label,
190203
x = x,
191204
y = y,
205+
remove_zero_columns = remove_zero_columns,
192206
basic_table_args = basic_table_args,
193207
decorators = decorators
194208
)
@@ -207,7 +221,7 @@ tm_t_crosstable <- function(label = "Cross Table",
207221
}
208222

209223
# UI function for the cross-table module
210-
ui_t_crosstable <- function(id, x, y, show_percentage, show_total, pre_output, post_output, ...) {
224+
ui_t_crosstable <- function(id, x, y, show_percentage, show_total, remove_zero_columns, pre_output, post_output, ...) {
211225
args <- list(...)
212226
ns <- NS(id)
213227
is_single_dataset <- teal.transform::is_single_dataset(x, y)
@@ -245,7 +259,8 @@ ui_t_crosstable <- function(id, x, y, show_percentage, show_total, pre_output, p
245259
bslib::accordion_panel(
246260
title = "Table settings",
247261
checkboxInput(ns("show_percentage"), "Show column percentage", value = show_percentage),
248-
checkboxInput(ns("show_total"), "Show total column", value = show_total)
262+
checkboxInput(ns("show_total"), "Show total column", value = show_total),
263+
checkboxInput(ns("remove_zero_columns"), "Remove zero-only columns", value = remove_zero_columns)
249264
)
250265
),
251266
ui_decorate_teal_data(ns("decorator"), decorators = select_decorators(args$decorators, "table"))
@@ -259,7 +274,7 @@ ui_t_crosstable <- function(id, x, y, show_percentage, show_total, pre_output, p
259274
}
260275

261276
# Server function for the cross-table module
262-
srv_t_crosstable <- function(id, data, reporter, filter_panel_api, label, x, y, basic_table_args, decorators) {
277+
srv_t_crosstable <- function(id, data, reporter, filter_panel_api, label, x, y, remove_zero_columns, basic_table_args, decorators) {
263278
with_reporter <- !missing(reporter) && inherits(reporter, "Reporter")
264279
with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI")
265280
checkmate::assert_class(data, "reactive")
@@ -352,6 +367,7 @@ srv_t_crosstable <- function(id, data, reporter, filter_panel_api, label, x, y,
352367

353368
show_percentage <- input$show_percentage
354369
show_total <- input$show_total
370+
remove_zero_columns <- input$remove_zero_columns
355371

356372
plot_title <- paste(
357373
"Cross-Table of",
@@ -368,7 +384,7 @@ srv_t_crosstable <- function(id, data, reporter, filter_panel_api, label, x, y,
368384
ANL
369385
)
370386

371-
teal.code::eval_code(
387+
obj <- teal.code::eval_code(
372388
merged$anl_q_r(),
373389
substitute(
374390
expr = {
@@ -413,14 +429,32 @@ srv_t_crosstable <- function(id, data, reporter, filter_panel_api, label, x, y,
413429
)
414430
) %>%
415431
teal.code::eval_code(
416-
substitute(
417-
expr = {
418-
ANL <- tern::df_explicit_na(ANL)
419-
table <- rtables::build_table(lyt = table, df = ANL[order(ANL[[y_name]]), ])
420-
},
421-
env = list(y_name = y_name)
422-
)
432+
expression(ANL <- tern::df_explicit_na(ANL))
423433
)
434+
435+
if (remove_zero_columns) {
436+
obj <- obj %>%
437+
teal.code::eval_code(
438+
substitute(
439+
expr = {
440+
ANL[[y_name]] <- droplevels(ANL[[y_name]])
441+
table <- rtables::build_table(lyt = table, df = ANL[order(ANL[[y_name]]), ])
442+
},
443+
env = list(y_name = y_name)
444+
)
445+
)
446+
} else {
447+
obj <- obj %>%
448+
teal.code::eval_code(
449+
substitute(
450+
expr = {
451+
table <- rtables::build_table(lyt = table, df = ANL[order(ANL[[y_name]]), ])
452+
},
453+
env = list(y_name = y_name)
454+
)
455+
)
456+
}
457+
obj
424458
})
425459

426460
decorated_output_q <- srv_decorate_teal_data(

man/tm_t_crosstable.Rd

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)