Skip to content

Add levels argument to add_difference() (tbl_summary + tbl_svysummary) to compare two groups (#2151)#2423

Merged
ddsjoberg merged 12 commits into
mainfrom
feat/2151-add-difference-levels
Jul 9, 2026
Merged

Add levels argument to add_difference() (tbl_summary + tbl_svysummary) to compare two groups (#2151)#2423
ddsjoberg merged 12 commits into
mainfrom
feat/2151-add-difference-levels

Conversation

@ddsjoberg

@ddsjoberg ddsjoberg commented Jun 27, 2026

Copy link
Copy Markdown
Owner

What changes are proposed in this pull request?

Added a levels argument to add_difference.tbl_summary() and add_difference.tbl_svysummary() to select which two by groups to compare. This makes add_difference() usable when by= has more than two levels, and lets users flip the direction of the difference for two-level by variables. (#2151)

The difference is computed as levels[1] minus levels[2]. When supplied, the data is subset to the two selected levels with the by factor re-leveled, while all summary statistic columns are retained. A footnote names the compared pair and direction.

# data frame
trial |>
  tbl_summary(by = grade, include = c(age, marker), missing = "no") |>
  add_difference(levels = c("I", "III"))   # difference = I - III

# survey design
survey::svydesign(~1, data = trial, weights = ~1) |>
  tbl_svysummary(by = grade, include = c(age, marker), missing = "no") |>
  add_difference(levels = c("I", "III"))   # difference = I - III
  • New levels argument (default NULL), a length-2 vector of by-level values matched by value.
  • Required when by has 3+ levels; the previous "exactly two levels" error now points users to levels.
  • Optional for two-level by, where reversing the pair flips the sign.
  • Validation: length-2, distinct, non-missing, and both values must be existing by levels (error lists valid levels).
  • Both methods share one private helper (.process_difference_levels()) for validation and subsetting. The helper is survey-aware: for tbl_svysummary() it subsets and re-levels the survey.design (via survey::subset()), restoring column labels that subsetting strips.

If there is an GitHub issue associated with this pull request, please provide link.

Closes #2151


Reviewer Checklist (if item does not apply, mark is as complete)

  • PR branch has pulled the most recent updates from main branch.
  • If a bug was fixed, a unit test was added.
  • Run pkgdown::build_site(). Check the R console for errors, and review the rendered website.
  • Code coverage is suitable for any new functions/features: devtools::test_coverage()
  • usethis::use_spell_check() runs with no spelling errors in documentation
  • All GitHub Action workflows pass with a ✅

When the branch is ready to be merged into master:

  • Update NEWS.md with the changes from this pull request under the heading "# gtsummary (development version)". If there is an issue associated with the pull request, reference it in parentheses at the end update (see NEWS.md for examples).
  • Increment the version number using usethis::use_version(which = "dev")
  • Run usethis::use_spell_check() again
  • Approve Pull Request
  • Merge the PR. Please use "Squash and merge".

ddsjoberg and others added 2 commits June 27, 2026 04:52
Add a levels argument to add_difference.tbl_summary() so users can select
which two by-variable groups to compare. This makes add_difference() usable
when tbl_summary(by=) has more than two levels, and lets users flip the
direction of the difference for two-level by variables.

The difference is computed as levels[1] minus levels[2]. When supplied, the
data is subset to the two selected levels with the by factor re-leveled, while
the full set of summary statistic columns is retained. A footnote names the
compared pair and direction.

Co-authored-by: Ona <no-reply@ona.com>
The levels argument subset x$inputs$data for the difference calculation but
left the subset on the returned object, permanently discarding the other
groups' data. Capture the original data before subsetting and restore it
before returning, so the calculation uses the subset while the returned
object keeps the full data. Add a regression test.

Co-authored-by: Ona <no-reply@ona.com>
@ddsjoberg ddsjoberg requested a review from larmarange June 27, 2026 05:26
@ddsjoberg

Copy link
Copy Markdown
Owner Author

Hi @larmarange , hope you've been well. Do you want to take a look at this? You were interested in this functionality to reverse the difference calculation for your before-after tables.

@ddsjoberg ddsjoberg marked this pull request as ready for review June 29, 2026 03:19
ddsjoberg and others added 6 commits June 28, 2026 21:31
Co-authored-by: Ona <no-reply@ona.com>
Mirrors the levels argument added to add_difference.tbl_summary(): select
which two by groups to compare (levels[1] - levels[2]), required when by has
3+ levels and able to flip direction for two-level by. The shared
.process_difference_levels() helper is generalized to handle survey designs
(subset and re-level via survey::subset, restoring stripped column labels).

Co-authored-by: Ona <no-reply@ona.com>
@ddsjoberg ddsjoberg changed the title Add levels argument to add_difference.tbl_summary() to compare two groups (#2151) Add levels argument to add_difference() (tbl_summary + tbl_svysummary) to compare two groups (#2151) Jun 30, 2026
ddsjoberg and others added 2 commits June 30, 2026 20:24
The levels direction footnote (e.g. 'Difference: I - III') was overwriting the
footnote describing the difference method/test. Use the internal
.modify_footnote_header(replace = FALSE) so both footnotes are shown.

Co-authored-by: Ona <no-reply@ona.com>

@larmarange larmarange left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks a lot @ddsjoberg

Everything looks right to me

@ddsjoberg

Copy link
Copy Markdown
Owner Author

Thank you @larmarange !

@ddsjoberg ddsjoberg merged commit bef2c37 into main Jul 9, 2026
8 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add_difference() pick two groups to compare update

2 participants