Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4a6fec3
initial ard_compare()
malanbos Nov 11, 2025
214de0b
remove unneeded check
malanbos Dec 1, 2025
e836002
split out checking of environments for ard_compare
malanbos Dec 1, 2025
ce571cb
split out functions to separate helper file
malanbos Dec 1, 2025
e73c917
Allowed ard_compare() to proceed without aborting when ARDs have non-…
malanbos Dec 1, 2025
ea53426
qualify utils::head
malanbos Dec 1, 2025
654f965
Merge branch 'main' into main
ddsjoberg Dec 12, 2025
26d1f1e
rename
malanbos Jan 18, 2026
964a16c
Merge branch 'main' into main
ddsjoberg Jan 23, 2026
1eaf3c0
[skip actions] Bump version to 0.7.1.9005
ddsjoberg Jan 23, 2026
fc432de
rename ard_compare to compare_ard
malanbos Jan 26, 2026
cfd95e9
[skip actions] Bump version to 0.7.1.9006
malanbos Jan 26, 2026
968fd8d
Update R/compare_ard.R
malanbos Feb 9, 2026
95c7302
[skip actions] Bump version to 0.7.1.9007
malanbos Feb 9, 2026
ad07a7f
Update R/compare_ard_helpers.R
malanbos Feb 9, 2026
d950774
[skip actions] Bump version to 0.7.1.9008
malanbos Feb 9, 2026
b346f53
Update R/compare_ard.R
malanbos Feb 9, 2026
7c8aebc
[skip actions] Bump version to 0.7.1.9009
malanbos Feb 9, 2026
b7cca66
Update compare_ard() to use all.equal() with tolerance and check.attr…
malanbos Feb 23, 2026
ac1c345
[skip actions] Bump version to 0.7.1.9010
malanbos Feb 23, 2026
e4b5089
Add .claude to .Rbuildignore to suppress R CMD check NOTE
malanbos Feb 23, 2026
d0444ef
[skip actions] Bump version to 0.7.1.9011
malanbos Feb 23, 2026
120ced9
Update example dataset name in compare_ard()
malanbos Feb 23, 2026
afebb5f
[skip actions] Bump version to 0.7.1.9012
malanbos Feb 23, 2026
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 .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
^\.covrignore$
^\.gitlab-ci\.yml$
^CODE_OF_CONDUCT\.md$
^\.claude$
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ docs
tests/testthat/_snaps/**/*.new.md
tests/testthat/_snaps/**/*.new.svg
revdep
.Rhistory
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: cards
Title: Analysis Results Data
Version: 0.7.1.9004
Version: 0.7.1.9012
Authors@R: c(
person("Daniel D.", "Sjoberg", , "danield.sjoberg@gmail.com", role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-0862-2018")),
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export(captured_condition_as_message)
export(cards_select)
export(check_ard_structure)
export(check_list_elements)
export(compare_ard)
export(compute_formula_selector)
export(contains)
export(continuous_summary_fns)
Expand Down
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# cards 0.7.1.9004
# cards 0.7.1.9012

* Adding `ard_tabulate_rows()` function to tabulate the number of rows in a data frame. (#531)

Expand Down
78 changes: 78 additions & 0 deletions R/compare_ard.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#' Compare ARDs
#'
#' @description
#' `compare_ard()` compares columns of two ARDs row-by-row using a shared set
#' of key columns. Rows where the column values differ are returned.
#'
#' @param x (`card`)\cr
#' first ARD to compare.
#' @param y (`card`)\cr
#' second ARD to compare.
#' @param keys ([`tidy-select`][dplyr::dplyr_tidy_select])\cr
#' columns identifying unique records. The intersection of the selected
#' columns in both ARDs is used. Default is
#' `c(all_ard_groups(), all_ard_variables(), any_of(c("variable", "variable_level", "stat_name")))`.
#' @param compare ([`tidy-select`][dplyr::dplyr_tidy_select])\cr
#' columns to compare between the two ARDs. Default is
#' `any_of(c("stat_label", "stat", "stat_fmt"))`.
#' @param tolerance (`numeric(1)`)\cr
#' numeric tolerance passed to `all.equal()` for numeric comparisons.
#' Default is `sqrt(.Machine$double.eps)`.
#' @param check.attributes (`logical(1)`)\cr
#' logical passed to `all.equal()` indicating whether object attributes
#' (e.g. names) should be compared. Default is `TRUE`.
#'
#' @return a named list of class `"ard_comparison"` containing:
#'
#' - `rows_in_x_not_y`: data frame of rows present in `x` but not in `y`
#' (based on key columns)
#' - `rows_in_y_not_x`: data frame of rows present in `y` but not in `x`
#' (based on key columns)
#' - `compare`: a named list where each element is a data frame containing
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe would call diff?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you mean rename the "compare" to "diff"? That's fine with me yes.

#' the key columns, the compared column values from both ARDs, and a
#' `difference` column with the `all.equal()` description for rows where
#' values differ
#'
#' @export
#'
#' @examples
#' base <- ard_summary(ADSL, by = ARM, variables = AGE)
#' compare <- ard_summary(dplyr::mutate(ADSL, AGE = AGE + 1),
#' by = ARM,
#' variables = AGE)
#'
#' compare_ard(base, compare)$compare$stat
#'
compare_ard <- function(x,
Copy link
Contributor

Choose a reason for hiding this comment

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

I really like the construction and concept of the main function. The helper functions are a bit of a Dedalus but I will take a closer look during the week ;)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure! And I learnt a new word here :)

y,
keys = c(all_ard_groups(), all_ard_variables(), any_of(c("variable", "variable_level", "stat_name"))),
compare = any_of(c("stat_label", "stat", "stat_fmt")),
tolerance = sqrt(.Machine$double.eps),
check.attributes = TRUE) {
set_cli_abort_call()

check_class(x, cls = "card")
check_class(y, cls = "card")

# process keys and compare arguments -----------------------------------------
keys <- .process_keys_arg(x, y, keys = {{ keys }})
compare <- .process_compare_arg(x, y, compare = {{ compare }})

# check for duplicates in keys -----------------------------------------------
.check_keys_unique(x, keys, arg_name = "x")
.check_keys_unique(y, keys, arg_name = "y")

# initialize results list ----------------------------------------------------
results <- rlang::rep_named(c("rows_in_x_not_y", "rows_in_y_not_x"), list(NULL))
results[["compare"]] <- rlang::rep_named(compare, list(NULL))

# find rows present in one ARD but not the other -----------------------------
results[["rows_in_x_not_y"]] <- .compare_rows(x, y, keys)
results[["rows_in_y_not_x"]] <- .compare_rows(y, x, keys)

# compare columns and find mismatches ----------------------------------------
results[["compare"]] <- .compare_columns(x, y, keys, compare, tolerance, check.attributes)

# return results with class --------------------------------------------------
structure(results, class = c("ard_comparison", class(results)))
}
Loading