Skip to content

Conversation

@llrs-roche
Copy link
Contributor

@llrs-roche llrs-roche commented Dec 9, 2025

Pull Request

Fixes https://github.com/insightsengineering/coredev-tasks/issues/676
See also https://github.com/insightsengineering/coredev-tasks/issues/658

Add a new module using crane -> gtsummary->gt to summarise tables.

TODO:

  • Decide UX interface
    • Provide only what's easy for the users: which variable use to stratify, which variables should be included and how to handle the missing values and percentage.
      Other input should be defined by the app-developer.
  • Implement the server function
  • Expose the add_* functions on the module.
  • Add wrappers to this functions (probably on tmc for making specific tables)
Example app

load_all("../teal.modules.general") # this branch
data <- within(teal_data(), {
  ADSL <- teal.data::rADSL
  ADSL2 <- ADSL
})
join_keys(data) <- default_cdisc_join_keys[names(data)]
init(
  data = data,
  modules = modules(
    tm_gt_tbl_summary(
      by = data_extract_spec(dataname = "ADSL", 
                             select = select_spec(
                               choices = c("SEX", "COUNTRY", "SITEID", "ACTARM"),
                               selected = "SEX",
                               multiple = FALSE)
      ),
      include = data_extract_spec(dataname = "ADSL",
                                  select = select_spec(
                                    choices = c("SITEID", "COUNTRY", "ACTARM"),
                                    selected = "SITEID",
                                    multiple = TRUE,
                                    fixed = FALSE
                                  )
      )
    )
  )
) |> runApp()

image

I haven't added more UI parameters are they are complex, a mix of list, formulas and characters that are not easily translated to the UI (without a free text).

For a full implementation these tasks would need to be taken:

@llrs-roche llrs-roche added the core label Dec 9, 2025
@llrs-roche llrs-roche marked this pull request as ready for review December 11, 2025 10:07
@github-actions
Copy link
Contributor

github-actions bot commented Dec 11, 2025

Unit Tests Summary

  1 files   24 suites   15m 57s ⏱️
168 tests 162 ✅ 5 💤 1 ❌
484 runs  478 ✅ 5 💤 1 ❌

For more details on these failures, see this check.

Results for commit 920b107.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 11, 2025

Unit Test Performance Difference

Test Suite $Status$ Time on main $±Time$ $±Tests$ $±Skipped$ $±Failures$ $±Errors$
shinytest2-tm_a_pca 💔 $146.23$ $+3.20$ $0$ $0$ $0$ $0$
shinytest2-tm_a_regression 💔 $69.81$ $+1.41$ $0$ $0$ $0$ $0$
shinytest2-tm_data_table 💔 $28.50$ $+1.21$ $0$ $0$ $0$ $0$
shinytest2-tm_g_bivariate 💔 $91.71$ $+1.51$ $0$ $0$ $0$ $0$
shinytest2-tm_g_distribution 💔 $59.36$ $+1.00$ $0$ $0$ $0$ $0$
shinytest2-tm_g_scatterplot 💔 $75.51$ $+1.14$ $0$ $0$ $0$ $0$
shinytest2-tm_outliers 💔 $147.90$ $+1.03$ $0$ $0$ $0$ $0$
shinytest2-tm_variable_browser 💔 $87.54$ $+1.76$ $0$ $0$ $0$ $0$
Additional test case details
Test Suite $Status$ Time on main $±Time$ Test Case
examples 👶 $+0.06$ example_tm_gt_tbl_summary.Rd

Results for commit a4d9f3c

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 11, 2025

badge

Code Coverage Summary

Filename                      Stmts    Miss  Cover    Missing
--------------------------  -------  ------  -------  -------------------------------------------
R/geom_mosaic.R                  73      73  0.00%    37-225
R/tm_a_pca.R                    864     864  0.00%    141-1132
R/tm_a_regression.R             751     751  0.00%    180-1027
R/tm_data_table.R               200     200  0.00%    100-348
R/tm_file_viewer.R              172     172  0.00%    50-257
R/tm_front_page.R               143     132  7.69%    77-246
R/tm_g_association.R            320     320  0.00%    161-547
R/tm_g_bivariate.R              672     408  39.29%   332-788, 829, 940, 957, 975, 986-1008
R/tm_g_distribution.R          1106    1106  0.00%    156-1404
R/tm_g_response.R               345     345  0.00%    179-594
R/tm_g_scatterplot.R            709     709  0.00%    261-1065
R/tm_g_scatterplotmatrix.R      272     253  6.99%    200-501, 562, 576
R/tm_gt_tbl_summary.R           176     176  0.00%    102-338
R/tm_missing_data.R            1172    1172  0.00%    126-1475
R/tm_outliers.R                1029    1029  0.00%    162-1341
R/tm_rmarkdown.R                154      68  55.84%   144-196, 225-240, 284-285, 345-368
R/tm_t_crosstable.R             263     263  0.00%    177-482
R/tm_variable_browser.R         887     881  0.68%    89-1113, 1164-1347
R/utils.R                       185     120  35.14%   87-250, 279-305, 317-326, 331, 345-364, 453
R/zzz.R                           2       2  0.00%    2-3
TOTAL                          9495    9044  4.75%

Diff against main

Filename                 Stmts    Miss  Cover
---------------------  -------  ------  --------
R/tm_gt_tbl_summary.R     +176    +176  +100.00%
TOTAL                     +176    +176  -0.09%

Results for commit: 42080fe

Minimum allowed coverage is 80%

♻️ This comment has been updated with latest results


# sort
if (!is.null(sort)) {
validate(need(all(vapply(sort, is, class2 = "formula", logical(1L))), "All elements of sort should be formulas"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
validate(need(all(vapply(sort, is, class2 = "formula", logical(1L))), "All elements of sort should be formulas"))
validate(need(all(vapply(list(sort), is, class2 = "formula", logical(1L))), "All elements of sort should be formulas"))

sort has to be list since we're running it against vapply.

Otherwise, I got the validation:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you use sort = all_categorical(FALSE) ~ "alphanumeric"? I should change a bit the validation to account for that case. The proposed change I think wouldn't work for sort = list(all_categorical(FALSE) ~ "alphanumeric", all_numeric(TRUE) ~ "alphanumeric") (pseudocode to show how I thought this parameter would be used).

missing_text = "<Missing>",
missing_stat = "{N_nonmiss}",
sort = gtsummary::all_categorical(FALSE) ~ "alphanumeric",
include = tidyselect::everything(),
Copy link
Contributor

@gogonzo gogonzo Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work. I'm sceptical if tidyselect::everything can be used with data_extract_spec. tidyselect::everything() fails when forced (executed outside of tidyselect::eval_tidy). Referring to the comment I think that if picks succeeds and will be implemented this will have to be deprecated and changed to picks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the default arguments won't work. I just wanted to have here to make it easier for users to match the arguments of the gtsummary function to the module ones. I'll change it.

My comment about picks is now what is accepted and what is not accepted but about what is the R code shown the users. If a users use: picks(variables(where(is.numeric))) but we evaluate that and replace by the name of the variables ("AGE", ...) , the "Show R code" won't show that the app developer set the selection to the numeric values. It will only show the variables selected: include = where(is.numeric) vs include = c(AGE, ...). There is some information lost there that could be relevant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, unfortunately original parameter will be lost. I don't think we can preserve tidyselect specs to use them in the final visualization.
Let's explore this more with picks when it will be reviewed more seriously 👍

) {
message("Initializing tm_gt_tbl_summary")
checkmate::assert_string(label)
if (inherits(by, "data_extract_spec")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to use tidyselect and assert on this argument, then you need to handle this in a specific way. See here:
https://github.com/insightsengineering/teal.transform/blob/621603df655f4c051de612f1c35a66cf44a81756/R/0-picks.R#L427

@llrs-roche
Copy link
Contributor Author

Closing this PR as development has moved elsewhere.

@llrs-roche llrs-roche closed this Dec 16, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Dec 16, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants