Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
ec44372
Explore heatmap and tile map
llrs-roche Sep 23, 2025
4593c88
Fix lintr names
llrs-roche Oct 3, 2025
586b960
Replace table by a plot
llrs-roche Oct 3, 2025
c4a13cc
Fix lint comments
llrs-roche Oct 3, 2025
dda7615
[skip style] [skip vbump] Restyle files
github-actions[bot] Oct 3, 2025
ea38ac1
Fix lintr issues
llrs-roche Oct 3, 2025
ee7f4b6
Merge branch '495_plot_missing@main' of github.com:insightsengineerin…
llrs-roche Oct 3, 2025
1159a49
Merge branch 'main' into 495_plot_missing@main
llrs-roche Oct 3, 2025
c296936
Split evaluation to load libraries
llrs-roche Oct 3, 2025
56020d4
Merge branch 'main' into 495_plot_missing@main
m7pr Oct 8, 2025
5e3080d
Use "library(pkg)" instead of 'library("pkg")' #nolint
llrs-roche Oct 9, 2025
484b91c
Use dot at the end of lint comment
llrs-roche Oct 9, 2025
d2673e6
Simplify code branch
llrs-roche Oct 13, 2025
558f666
[skip style] [skip vbump] Restyle files
github-actions[bot] Oct 13, 2025
5c4b580
[skip roxygen] [skip vbump] Roxygen Man Pages Auto Update
github-actions[bot] Oct 13, 2025
d2a903f
Merge branch 'main' into 495_plot_missing@main
llrs-roche Oct 15, 2025
08951f5
Merge branch 'main' into 495_plot_missing@main
llrs-roche Oct 16, 2025
bcf8803
Merge branch 'main' into 495_plot_missing@main
m7pr Oct 17, 2025
ef399e0
Fix logic
llrs-roche Oct 17, 2025
f383cc7
Avoid ggplot2 warnings
llrs-roche Oct 17, 2025
fed8c46
Check feedback from copilot
llrs-roche Oct 17, 2025
6d71798
[skip style] [skip vbump] Restyle files
github-actions[bot] Oct 17, 2025
22faabd
Fix misspelling on linters
llrs-roche Oct 20, 2025
3cb8e61
Fix style
llrs-roche Oct 20, 2025
463f61e
Do not reduce the timeout from the default 4s
llrs-roche Oct 20, 2025
b576f8e
[skip style] [skip vbump] Restyle files
github-actions[bot] Oct 20, 2025
3696675
Fix typo
llrs-roche Oct 20, 2025
949a35b
Avoid skipping tests
llrs-roche Oct 20, 2025
ed17c6b
Update code based on https://github.com/insightsengineering/teal.modu…
llrs-roche Oct 20, 2025
188fa05
Add req to resolve the app faster
llrs-roche Oct 21, 2025
f1a180b
[skip style] [skip vbump] Restyle files
github-actions[bot] Oct 21, 2025
1006fa9
Prefix functions with their packages
llrs-roche Oct 21, 2025
8a311f1
Fix typo
llrs-roche Oct 21, 2025
5b4226a
Fix package
llrs-roche Oct 21, 2025
5a3bea4
Merge branch 'main' into 495_plot_missing@main
llrs-roche Nov 17, 2025
4b6e867
[skip roxygen] [skip vbump] Roxygen Man Pages Auto Update
github-actions[bot] Nov 17, 2025
4c1692e
Merge branch 'main' into 495_plot_missing@main
m7pr Nov 17, 2025
46c9ec3
Merge from main
llrs-roche Nov 20, 2025
8845ead
Test CI changes
llrs-roche Nov 21, 2025
ef59971
ci: test ci and revert in the next commit
averissimo Nov 21, 2025
1732dfd
Update R/tm_g_association.R
llrs-roche Nov 21, 2025
7329984
adds new file to remove later
averissimo Nov 21, 2025
c13063f
chore: cleanup extra files and fix name
averissimo Nov 21, 2025
ad5c396
chore: remove added file
averissimo Nov 21, 2025
31957c5
Remove mention to ggmosaic
llrs-roche Nov 24, 2025
d17b93b
Remove extra dependency
llrs-roche Nov 24, 2025
5626cc3
Apply suggestions from code review
llrs-roche Nov 24, 2025
cd0880a
Use main now that https://github.com/insightsengineering/r.pkg.templa…
llrs-roche Nov 24, 2025
b89baee
Merge branch '495_plot_missing@main' of github.com:insightsengineerin…
llrs-roche Nov 24, 2025
5c1bd30
Merge branch 'main' into 495_plot_missing@main
llrs-roche Nov 25, 2025
a2eabe6
Merged origin/495_plot_missing@main into 495_plot_missing@main
llrs-roche Nov 25, 2025
ce2abbe
Merge branch 'main' into 495_plot_missing@main
m7pr Nov 25, 2025
b77b58e
Merge branch 'main' into 495_plot_missing@main
llrs-roche Nov 26, 2025
4bedaa3
update insightsengineering/teal@bring_tests
m7pr Nov 27, 2025
e65605f
Update DESCRIPTION
m7pr Nov 27, 2025
5eed0fe
Update check.yaml to allow PR events on any branch
m7pr Nov 27, 2025
1a5e934
Add lintr issue
llrs-roche Nov 28, 2025
b46d233
Fix summary plot from anyna
llrs-roche Nov 28, 2025
3d60bc4
Update id
llrs-roche Dec 1, 2025
e183a3c
Fix module so plot is shown
llrs-roche Dec 1, 2025
6d7b42f
Fix file_viewer tests
llrs-roche Dec 1, 2025
466d5e7
Simplify selectors (and lintr notes)
llrs-roche Dec 1, 2025
70bbaf0
Add more pause to ensure the checks are when the app is ready
llrs-roche Dec 1, 2025
d480e4a
Update ids
llrs-roche Dec 1, 2025
ddc10db
Remove test about a table no longer present
llrs-roche Dec 2, 2025
b72941c
Remove requirements that prevented displaying the output
llrs-roche Dec 2, 2025
9c17dd9
Update the ids of the plots
llrs-roche Dec 2, 2025
d1f46c9
Apply suggestions from code review
llrs-roche Dec 2, 2025
605abe2
Update R/tm_missing_data.R
llrs-roche Dec 2, 2025
78021ce
Update R/tm_missing_data.R
llrs-roche Dec 2, 2025
5677cc2
Fix logic for validation error
llrs-roche Dec 2, 2025
a95713e
Update R/tm_missing_data.R
llrs-roche Dec 2, 2025
d3d5737
Change label according to user selection
llrs-roche Dec 3, 2025
a338231
Merge branch '495_plot_missing@main' of github.com:insightsengineerin…
llrs-roche Dec 3, 2025
01d9758
Add back the branch
llrs-roche Dec 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Imports:
tools,
utils
Suggests:
formatters (>= 0.5.11),
knitr (>= 1.42),
logger (>= 0.4.0),
nestcolor (>= 0.1.0),
Expand Down
2 changes: 1 addition & 1 deletion R/tm_a_pca.R
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ srv_a_pca <- function(id, data, dat, plot_height, plot_width, ggplot2_args, deco
teal.reporter::teal_card(obj),
teal.reporter::teal_card("## Module's code")
)
teal.code::eval_code(obj, 'library("ggplot2");library("dplyr");library("tidyr")') # nolint: quotes
teal.code::eval_code(obj, 'library("ggplot2");library("dplyr");library("tidyr")') # nolint: quotes_lintr
})
anl_merged_q <- reactive({
req(anl_merged_input())
Expand Down
6 changes: 3 additions & 3 deletions R/tm_a_regression.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
#' It takes the form of `c(value, min, max)` and it is passed to the `value_min_max`
#' argument in `teal.widgets::optionalSliderInputValMinMax`.
#'
# nolint start: line_length.
# nolint start: line_length
#' @param ggplot2_args `r roxygen_ggplot2_args_param("Response vs Regressor", "Residuals vs Fitted", "Scale-Location", "Cook's distance", "Residuals vs Leverage", "Cook's dist vs Leverage")`
# nolint end: line_length.
# nolint end: line_length
#'
#' @inherit shared_params return
#'
Expand Down Expand Up @@ -465,7 +465,7 @@ srv_a_regression <- function(id,
teal.reporter::teal_card(obj),
teal.reporter::teal_card("## Module's code")
)
teal.code::eval_code(obj, 'library("ggplot2");library("dplyr")') # nolint: quotes
teal.code::eval_code(obj, 'library("ggplot2");library("dplyr")') # nolint: quotes_lintr
})

anl_merged_q <- reactive({
Expand Down
2 changes: 1 addition & 1 deletion R/tm_data_table.R
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ srv_data_table <- function(id,
teal::validate_has_data(df, min_nrow = 1L, msg = paste("data", dataname, "is empty"))
qenv <- teal.code::eval_code(
data(),
'library("dplyr");library("DT")' # nolint: quotes.
'library("dplyr");library("DT")' # nolint: quotes_lintr.
)
teal.code::eval_code(
qenv,
Expand Down
6 changes: 3 additions & 3 deletions R/tm_g_association.R
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ tm_g_association <- function(label = "Association",
show_association = TRUE,
plot_height = c(600, 400, 5000),
plot_width = NULL,
distribution_theme = c("gray", "bw", "linedraw", "light", "dark", "minimal", "classic", "void"), # nolint: line_length.
association_theme = c("gray", "bw", "linedraw", "light", "dark", "minimal", "classic", "void"), # nolint: line_length.
distribution_theme = c("gray", "bw", "linedraw", "light", "dark", "minimal", "classic", "void"), # nolint line_length_lintr.
association_theme = c("gray", "bw", "linedraw", "light", "dark", "minimal", "classic", "void"), # nolint line_length_lintr.
pre_output = NULL,
post_output = NULL,
ggplot2_args = teal.widgets::ggplot2_args(),
Expand Down Expand Up @@ -349,7 +349,7 @@ srv_tm_g_association <- function(id,
teal.reporter::teal_card(obj),
teal.reporter::teal_card("## Module's code")
)
teal.code::eval_code(obj, 'library("ggplot2");library("dplyr");library("ggmosaic")') # nolint: quotes
teal.code::eval_code(obj, 'library("ggplot2");library("dplyr");library("ggmosaic")') # nolint: quotes_lintr
})
anl_merged_q <- reactive({
req(anl_merged_input())
Expand Down
2 changes: 1 addition & 1 deletion R/tm_g_bivariate.R
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ srv_g_bivariate <- function(id,
obj %>%
teal.code::eval_code(
c(
'library("ggplot2");library("dplyr")', # nolint: quotes
'library("ggplot2");library("dplyr")', # nolint: quotes_lintr
as.expression(anl_merged_input()$expr)
)
)
Expand Down
14 changes: 7 additions & 7 deletions R/tm_g_distribution.R
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ srv_distribution <- function(id,
)

qenv <- reactive(
teal.code::eval_code(data(), 'library("ggplot2");library("dplyr")') # nolint quotes
teal.code::eval_code(data(), 'library("ggplot2");library("dplyr")') # nolint quotes_lintr
)

anl_merged_q <- reactive({
Expand Down Expand Up @@ -665,7 +665,7 @@ srv_distribution <- function(id,
"Group by variable must be `factor`, `character`, or `integer`"
)
)
qenv <- teal.code::eval_code(qenv, 'library("forcats")') # nolint quotes
qenv <- teal.code::eval_code(qenv, 'library("forcats")') # nolint quotes_lintr
qenv <- teal.code::eval_code(
qenv,
substitute(
Expand All @@ -683,7 +683,7 @@ srv_distribution <- function(id,
)
)

qenv <- teal.code::eval_code(qenv, 'library("forcats")') # nolint quotes
qenv <- teal.code::eval_code(qenv, 'library("forcats")') # nolint quotes_lintr
qenv <- teal.code::eval_code(
qenv,
substitute(
Expand Down Expand Up @@ -893,7 +893,7 @@ srv_distribution <- function(id,
}

if (length(t_dist) != 0 && main_type_var == "Density" && length(g_var) == 0 && length(s_var) == 0) {
qenv <- teal.code::eval_code(qenv, 'library("ggpp")') # nolint quotes
qenv <- teal.code::eval_code(qenv, 'library("ggpp")') # nolint quotes_lintr
qenv <- teal.code::eval_code(
qenv,
substitute(
Expand Down Expand Up @@ -1039,7 +1039,7 @@ srv_distribution <- function(id,
)

if (length(t_dist) != 0 && length(g_var) == 0 && length(s_var) == 0) {
qenv <- teal.code::eval_code(qenv, 'library("ggpp")') # nolint quotes
qenv <- teal.code::eval_code(qenv, 'library("ggpp")') # nolint quotes_lintr
qenv <- teal.code::eval_code(
qenv,
substitute(
Expand Down Expand Up @@ -1235,7 +1235,7 @@ srv_distribution <- function(id,
qenv <- common_q()

if (length(s_var) == 0 && length(g_var) == 0) {
qenv <- teal.code::eval_code(qenv, 'library("generics")') # nolint quotes
qenv <- teal.code::eval_code(qenv, 'library("generics")') # nolint quotes_lintr
qenv <- teal.code::eval_code(
qenv,
substitute(
Expand All @@ -1249,7 +1249,7 @@ srv_distribution <- function(id,
)
)
} else {
qenv <- teal.code::eval_code(qenv, 'library("tidyr")') # nolint quotes
qenv <- teal.code::eval_code(qenv, 'library("tidyr")') # nolint quotes_lintr
qenv <- teal.code::eval_code(
qenv,
substitute(
Expand Down
4 changes: 2 additions & 2 deletions R/tm_g_response.R
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ srv_g_response <- function(id,
)

qenv <- reactive(
teal.code::eval_code(data(), 'library("ggplot2");library("dplyr")') # nolint quotes
teal.code::eval_code(data(), 'library("ggplot2");library("dplyr")') # nolint quotes_lintr
)

anl_merged_q <- reactive({
Expand Down Expand Up @@ -524,7 +524,7 @@ srv_g_response <- function(id,
resp_cl = resp_cl,
hjust_value = if (swap_axes) "left" else "middle",
vjust_value = if (swap_axes) "middle" else -1,
position_anl2_value = if (!freq) quote(position_fill(0.5)) else quote(position_stack(0.5)), # nolint: line_length.
position_anl2_value = if (!freq) quote(position_fill(0.5)) else quote(position_stack(0.5)), # nolint line_length_lintr
anl3_y = if (!freq) 1.1 else as.name("ns"),
position_anl3_value = if (!freq) "fill" else "stack"
)
Expand Down
2 changes: 1 addition & 1 deletion R/tm_g_scatterplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ srv_g_scatterplot <- function(id,
teal.reporter::teal_card(obj),
teal.reporter::teal_card("## Module's code")
)
teal.code::eval_code(data(), 'library("ggplot2");library("dplyr")') # nolint quotes
teal.code::eval_code(data(), 'library("ggplot2");library("dplyr")') # nolint quotes_lintr
})

anl_merged_q <- reactive({
Expand Down
2 changes: 1 addition & 1 deletion R/tm_g_scatterplotmatrix.R
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ srv_g_scatterplotmatrix <- function(id,
teal.reporter::teal_card(obj),
teal.reporter::teal_card("## Module's code")
)
qenv <- teal.code::eval_code(obj, 'library("dplyr");library("lattice")') # nolint quotes
qenv <- teal.code::eval_code(obj, 'library("dplyr");library("lattice")') # nolint quotes_lintr
teal.code::eval_code(qenv, as.expression(anl_merged_input()$expr))
})

Expand Down
139 changes: 105 additions & 34 deletions R/tm_missing_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#' This module generates the following objects, which can be modified in place using decorators:
#' - `summary_plot` (`ggplot`)
#' - `combination_plot` (`grob` created with [ggplot2::ggplotGrob()])
#' - `by_variable_plot` (`ggplot`)
#' - `by_subject_plot` (`ggplot`)
#'
#' A Decorator is applied to the specific output using a named list of `teal_transform_module` objects.
Expand All @@ -34,6 +35,7 @@
#' decorators = list(
#' summary_plot = teal_transform_module(...), # applied only to `summary_plot` output
#' combination_plot = teal_transform_module(...), # applied only to `combination_plot` output
#' by_variable_plot = teal_transform_module(...) # applied only to `by_variable_plot` output
#' by_subject_plot = teal_transform_module(...) # applied only to `by_subject_plot` output
#' )
#' )
Expand Down Expand Up @@ -328,8 +330,7 @@ ui_missing_data <- function(id, by_subject_plot = FALSE) {
),
tabPanel(
"By Variable Levels",
teal.widgets::get_dt_rows(ns("levels_table"), ns("levels_table_rows")),
DT::dataTableOutput(ns("levels_table"))
teal.widgets::plot_with_settings_ui(id = ns("by_variable_plot")),
)
)
if (isTRUE(by_subject_plot)) {
Expand Down Expand Up @@ -1069,7 +1070,7 @@ srv_missing_data <- function(id,
})
})

summary_table_q <- reactive({
by_variable_plot_q <- reactive({
req(
input$summary_type == "By Variable Levels", # needed to trigger show r code update on tab change
common_code_q()
Expand All @@ -1079,7 +1080,7 @@ srv_missing_data <- function(id,
# extract the ANL dataset for use in further validation
anl <- common_code_q()[["ANL"]]

group_var <- input$group_by_var
group_var <- req(input$group_by_var)
validate(
need(
is.null(group_var) ||
Expand Down Expand Up @@ -1107,7 +1108,6 @@ srv_missing_data <- function(id,

qenv <- common_code_q()
teal.reporter::teal_card(qenv) <- c(teal.reporter::teal_card(qenv), "## Summary Table")

qenv <- if (!is.null(group_var)) {
common_code_libraries_q <- teal.code::eval_code(
qenv,
Expand Down Expand Up @@ -1151,10 +1151,87 @@ srv_missing_data <- function(id,
)
}

within(qenv, {
table <- rtables::df_to_tt(summary_data)
table
})
dev_ggplot2_args <- teal.widgets::ggplot2_args(
labs = list(
fill = if (input$count_type == "counts") "Missing counts" else "Missing percentage",
y = quote(ggplot2::element_blank())
)
)

all_ggplot2_args <- teal.widgets::resolve_ggplot2_args(
user_plot = ggplot2_args[["By Variable Levels"]],
user_default = ggplot2_args$default,
module_plot = dev_ggplot2_args
)

parsed_ggplot2_args <- teal.widgets::parse_ggplot2_args(
all_ggplot2_args,
ggtheme = input$ggtheme
)

# convert to ggplot
if (!is.null(group_vals)) {
ANL_q <- within(qenv, # nolint object_name_linter
{
keep_columns <- intersect(c(keys, group_var), colnames(ANL))
labels <- vapply(ANL, formatters::obj_label, character(1L))
ANL <- ANL %>%
filter(group_var_name %in% group_vals) %>%
pivot_longer(-keep_columns, values_transform = is.na) %>%
summarise(
.by = c(group_var_name, name),
value = sum(value), perc = value / n()
) %>%
mutate(label = labels[name])
},
keys = join_keys(qenv) |> unlist() |> unique(),
group_var_name = as.name(group_var),
group_var = group_var,
group_vals = group_vals
)
} else {
ANL_q <- within(qenv, # nolint object_name_linter
{
keep_columns <- intersect(c(keys, group_var), colnames(ANL))
labels <- vapply(ANL, formatters::obj_label, character(1L))
ANL <- ANL %>%
pivot_longer(-keep_columns, values_transform = is.na) %>%
summarise(
.by = c(group_var_name, name),
value = sum(value), perc = value / n()
) %>%
mutate(label = labels[name])
},
keys = join_keys(qenv) |> unlist() |> unique(),
group_var_name = as.name(group_var),
group_var = group_var
)
}
req(NROW(ANL_q$ANL) > 0)
browser(expr = group_var == "RACE")
tile <- within(ANL_q,
{
by_variable_plot <- ggplot(ANL, aes(group_var_name, label)) +
geom_tile(aes(fill = column)) +
geom_text(aes(label = scales::percent(perc)),
data = . %>% filter(perc > 0), color = "white"
) +
scale_x_discrete(expand = expansion()) +
scale_fill_gradient(high = "#ff2951ff", low = "grey90", labels = labels) +
labs +
ggthemes
},
group_var_name = as.name(group_var),
column = if (input$count_type == "counts") {
as.name("value")
} else {
as.name("perc")
},
labs = parsed_ggplot2_args$labs,
labels = if (input$count_type == "counts") quote(ggplot2::waiver()) else quote(scales::label_percent()),
ggthemes = parsed_ggplot2_args$ggtheme
)
tile
})

by_subject_plot_q <- reactive({
Expand Down Expand Up @@ -1300,11 +1377,11 @@ srv_missing_data <- function(id,
})
)

decorated_summary_table_q <- srv_decorate_teal_data(
id = "dec_summary_table",
data = summary_table_q,
decorators = select_decorators(decorators, "table"),
expr = quote(table)
decorated_by_variable_plot_q <- srv_decorate_teal_data(
id = "dec_by_variable_plot",
data = by_variable_plot_q,
decorators = select_decorators(decorators, "by_variable_plot"),
expr = quote(by_variable_plot)
)

decorated_by_subject_plot_q <- srv_decorate_teal_data(
Expand All @@ -1324,22 +1401,8 @@ srv_missing_data <- function(id,
req(decorated_combination_plot_q())[["combination_plot"]]
})

summary_table_r <- reactive({
q <- 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 {
DT::datatable(q[["summary_data"]])
}
by_variable_plot_r <- reactive({
req(decorated_by_variable_plot_q())[["by_variable_plot"]]
})

by_subject_plot_r <- reactive({
Expand All @@ -1361,9 +1424,14 @@ srv_missing_data <- function(id,
width = plot_width
)

output$levels_table <- DT::renderDataTable(summary_table_r())

pws3 <- teal.widgets::plot_with_settings_srv(
id = "by_variable_plot",
plot_r = by_variable_plot_r,
height = plot_height,
width = plot_width
)

pws4 <- teal.widgets::plot_with_settings_srv(
id = "by_subject_plot",
plot_r = by_subject_plot_r,
height = plot_height,
Expand All @@ -1375,8 +1443,11 @@ srv_missing_data <- function(id,
decorated_combination_plot_dims_q <- # nolint: object_length_linter.
set_chunk_dims(pws2, decorated_combination_plot_q)

decorated_by_variable_plot_dims_q <- # nolint: object_length_linter.
set_chunk_dims(pws3, decorated_by_variable_plot_q)

decorated_by_subject_plot_dims_q <- # nolint: object_length_linter.
set_chunk_dims(pws3, decorated_by_subject_plot_q)
set_chunk_dims(pws4, decorated_by_subject_plot_q)

decorated_final_q <- reactive({
sum_type <- req(input$summary_type)
Expand All @@ -1385,7 +1456,7 @@ srv_missing_data <- function(id,
} else if (sum_type == "Combinations") {
decorated_combination_plot_dims_q()
} else if (sum_type == "By Variable Levels") {
decorated_summary_table_q()
decorated_by_variable_plot_dims_q()
} else if (sum_type == "Grouped by Subject") {
decorated_by_subject_plot_dims_q()
}
Expand Down
Loading
Loading