Skip to content

Commit 7bb896a

Browse files
authored
Merge pull request #27 from openpharma/26-release-rbmiutils-015
26 release rbmiutils 015
2 parents 6fd6088 + 4a2c120 commit 7bb896a

6 files changed

Lines changed: 110 additions & 48 deletions

File tree

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: rbmiUtils
22
Title: Utility Functions to Support and Extend the 'rbmi' Package
3-
Version: 0.1.4.9000
3+
Version: 0.1.6.9000
44
Authors@R: c(
55
person("Mark", "Baillie", email = "bailliem@gmail.com", role = c("aut", "cre", "cph"),
66
comment = c(ORCID = "0000-0002-5618-0667")),

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# rbmiUtils (development version)
22

3+
# rbmiUtils 0.1.6
4+
5+
* Added additional tests for all utility functions.
6+
37
# rbmiUtils 0.1.4
48

59
* First release

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
[![Lifecycle:
99
experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)
10-
[![CRAN status](https://www.r-pkg.org/badges/version/rbmiUtils)](https://CRAN.R-project.org/package=rbmiUtils)
10+
![CRAN status](https://www.r-pkg.org/badges/version/rbmiUtils)
1111
[![R-CMD-check](https://github.com/openpharma/rbmiUtils/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/openpharma/rbmiUtils/actions/workflows/R-CMD-check.yaml)
1212
[![test-coverage](https://github.com/openpharma/rbmiUtils/actions/workflows/test-coverage.yaml/badge.svg)](https://github.com/openpharma/rbmiUtils/actions/workflows/test-coverage.yaml)
1313
<!-- badges: end -->
@@ -28,8 +28,8 @@ result tidying, and imputed data handling.
2828

2929
## Installation
3030

31-
You can install the development version of `rbmiUtils` from cran or
32-
GitHub:
31+
You can install the package from cran or the development version of
32+
`rbmiUtils` from GitHub:
3333

3434
| Type | Source | Command |
3535
|-------------|--------|---------------------------------------------------|

cran-comments.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@
22

33
0 errors | 0 warnings | 0 notes
44

5-
* This is a new release.
5+
* This is a minor update.
66

7-
This is a re-submission after initial review comments to be addressed.
7+
In this update, additional tests have been added to cover utility functions
8+
internal to the package and improve coverage.
89

9-
Fixes addressed include:
10-
* Description file. 'rbmi' in title and description now in single quotes.
11-
* Description update spelling out rbmi: reference based multiple imputation to provide context.
12-
* The example in gcomp_responder_multi.Rd has replaced \dontrun with \donttest. The example takes approx 8-9seconds to run.
13-
* A complete running example has been added to get_imputed_data.Rd removing the commented example. \donttest has been added to the example takes over 10seconds to run.
14-
15-
Thank you for your time and patience,
10+
* test-analysis_utils.R has been added to provide test coverage for all
11+
the analysis utility functions

inst/WORDLIST

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
ADMI
22
ANCOVA
3+
CMD
34
CRIT
45
FLN
56
HC
67
Lifecycle
78
Lukas
89
ORCID
910
Responder
10-
WIP
1111
beeca
12+
cran
1213
dervive
1314
interpretability
1415
modularly

tests/testthat/test-analysis_utils.R

Lines changed: 95 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ testthat::test_that("extract_covariates2 splits, trims, dedups, and handles NULL
33

44
x <- c("A:B", " C*D ", "E", "E", "F : G")
55
out <- extract_covariates2(x)
6-
expect_true(all(c("A","B","C","D","E","F","G") %in% out))
6+
expect_true(all(c("A", "B", "C", "D", "E", "F", "G") %in% out))
77
expect_equal(length(out), length(unique(out)))
88

99
# No operators, order preserved after trim
10-
expect_equal(extract_covariates2(c("AGE"," SEX ")), c("AGE","SEX"))
10+
expect_equal(extract_covariates2(c("AGE", " SEX ")), c("AGE", "SEX"))
1111
})
1212

1313
testthat::test_that("as_simple_formula2 builds intended formula; empty covars behavior is robust", {
14-
frm <- as_simple_formula2("Y", c("A","B:C","D*E"))
14+
frm <- as_simple_formula2("Y", c("A", "B:C", "D*E"))
1515
# Compare while ignoring whitespace around operators (especially `*`)
1616
expect_identical(gsub("\\s+", "", deparse(frm)), "Y~1+A+B:C+D*E")
1717
expect_identical(environment(frm), globalenv())
@@ -36,24 +36,42 @@ testthat::test_that("gcomp_responder runs, drops visit from model terms, returns
3636
testthat::skip_if_not_installed("beeca")
3737
set.seed(1)
3838
dat <- data.frame(
39-
Y = rbinom(160, 1, 0.45),
40-
TRT = factor(sample(c("Placebo","Drug"), 160, TRUE), levels = c("Placebo","Drug")),
41-
BASE= rnorm(160),
42-
VIS = sample(c("W4","W8"), 160, TRUE)
39+
Y = rbinom(160, 1, 0.45),
40+
TRT = factor(
41+
sample(c("Placebo", "Drug"), 160, TRUE),
42+
levels = c("Placebo", "Drug")
43+
),
44+
BASE = rnorm(160),
45+
VIS = sample(c("W4", "W8"), 160, TRUE)
46+
)
47+
vars <- list(
48+
outcome = "Y",
49+
group = "TRT",
50+
covariates = c("BASE", "TRT:BASE", "VIS"),
51+
visit = "VIS"
4352
)
44-
vars <- list(outcome = "Y", group = "TRT",
45-
covariates = c("BASE","TRT:BASE","VIS"), visit = "VIS")
4653

4754
out <- gcomp_responder(
48-
data = dat, vars = vars,
55+
data = dat,
56+
vars = vars,
4957
reference_levels = "Placebo",
50-
var_method = "Ge", type = "HC0", contrast = "diff"
58+
var_method = "Ge",
59+
type = "HC0",
60+
contrast = "diff"
5161
)
5262

5363
# Ensure VIS was not in the model terms
54-
frm <- stats::as.formula(paste0(vars$outcome, " ~ 1 + ",
55-
paste0(setdiff(unique(c(vars$group, extract_covariates2(vars$covariates))), vars$visit),
56-
collapse = " + ")))
64+
frm <- stats::as.formula(paste0(
65+
vars$outcome,
66+
" ~ 1 + ",
67+
paste0(
68+
setdiff(
69+
unique(c(vars$group, extract_covariates2(vars$covariates))),
70+
vars$visit
71+
),
72+
collapse = " + "
73+
)
74+
))
5775
m <- stats::glm(frm, data = dat, family = binomial())
5876
terms_used <- attr(stats::terms(m), "term.labels")
5977
expect_false(any(grepl("^VIS$", terms_used)))
@@ -62,7 +80,7 @@ testthat::test_that("gcomp_responder runs, drops visit from model terms, returns
6280
expect_true(any(grepl("^trt_", names(out))))
6381
expect_true(any(grepl("^lsm_", names(out))))
6482
for (nm in names(out)) {
65-
expect_true(all(c("est","se","df") %in% names(out[[nm]])))
83+
expect_true(all(c("est", "se", "df") %in% names(out[[nm]])))
6684
expect_type(out[[nm]]$est, "double")
6785
expect_type(out[[nm]]$se, "double")
6886
expect_true(is.na(out[[nm]]$df))
@@ -73,68 +91,95 @@ testthat::test_that("gcomp_responder defaults reference to first factor level (s
7391
testthat::skip_if_not_installed("beeca")
7492
set.seed(2)
7593
dat <- data.frame(
76-
Y = rbinom(80, 1, 0.5),
77-
TRT = factor(rep(c("Placebo","Drug"), each = 40), levels = c("Placebo","Drug")),
78-
BASE= rnorm(80),
94+
Y = rbinom(80, 1, 0.5),
95+
TRT = factor(
96+
rep(c("Placebo", "Drug"), each = 40),
97+
levels = c("Placebo", "Drug")
98+
),
99+
BASE = rnorm(80),
79100
VIS = "W4"
80101
)
81-
vars <- list(outcome = "Y", group = "TRT", covariates = c("BASE","VIS"), visit = "VIS")
102+
vars <- list(
103+
outcome = "Y",
104+
group = "TRT",
105+
covariates = c("BASE", "VIS"),
106+
visit = "VIS"
107+
)
82108

83109
# Should not error and should return structured results when reference not supplied
84110
out <- gcomp_responder(dat, vars)
85111
expect_true(length(out) > 0)
86-
expect_true(all(vapply(out, function(x) all(c("est","se","df") %in% names(x)), logical(1))))
112+
expect_true(all(vapply(
113+
out,
114+
function(x) all(c("est", "se", "df") %in% names(x)),
115+
logical(1)
116+
)))
87117
})
88118

89119
testthat::test_that("gcomp_responder validates that group is a factor (if implemented)", {
90120
testthat::skip_if_not_installed("beeca")
91121
dat <- data.frame(
92122
Y = rbinom(10, 1, 0.5),
93-
TRT = rep(c("Placebo","Drug"), each = 5), # character, not factor
123+
TRT = rep(c("Placebo", "Drug"), each = 5), # character, not factor
94124
BASE = rnorm(10),
95125
VIS = "W4"
96126
)
97127
vars <- list(outcome = "Y", group = "TRT", covariates = "BASE", visit = "VIS")
98128

99129
# If validation added, expect a clear error; otherwise allow skip.
100-
err <- try(gcomp_responder(dat, vars, reference_levels = "Placebo"), silent = TRUE)
130+
err <- try(
131+
gcomp_responder(dat, vars, reference_levels = "Placebo"),
132+
silent = TRUE
133+
)
101134
if (inherits(err, "try-error")) {
102135
expect_match(as.character(err), "(?i)factor|categorical")
103136
} else {
104-
testthat::skip("group-factor validation not implemented; skipping assertion.")
137+
testthat::skip(
138+
"group-factor validation not implemented; skipping assertion."
139+
)
105140
}
106141
})
107142

108143
testthat::test_that("gcomp_responder errors for invalid reference level (if implemented)", {
109144
testthat::skip_if_not_installed("beeca")
110145
dat <- data.frame(
111146
Y = rbinom(20, 1, 0.5),
112-
TRT = factor(rep(c("Placebo","Drug"), each = 10)),
147+
TRT = factor(rep(c("Placebo", "Drug"), each = 10)),
113148
BASE = rnorm(20),
114149
VIS = "W8"
115150
)
116151
vars <- list(outcome = "Y", group = "TRT", covariates = "BASE", visit = "VIS")
117152

118-
err <- try(gcomp_responder(dat, vars, reference_levels = "ActiveX"), silent = TRUE)
153+
err <- try(
154+
gcomp_responder(dat, vars, reference_levels = "ActiveX"),
155+
silent = TRUE
156+
)
119157
if (inherits(err, "try-error")) {
120158
expect_match(as.character(err), "(?i)reference.*level|not.*in.*levels")
121159
} else {
122-
testthat::skip("reference-level validation not implemented; skipping assertion.")
160+
testthat::skip(
161+
"reference-level validation not implemented; skipping assertion."
162+
)
123163
}
124164
})
125165

126166
testthat::test_that("gcomp_responder validates contrast against allowed set (either here or in beeca)", {
127167
testthat::skip_if_not_installed("beeca")
128168
dat <- data.frame(
129169
Y = rbinom(30, 1, 0.5),
130-
TRT = factor(rep(c("Placebo","Drug"), each = 15)),
170+
TRT = factor(rep(c("Placebo", "Drug"), each = 15)),
131171
BASE = rnorm(30),
132172
VIS = "W8"
133173
)
134174
vars <- list(outcome = "Y", group = "TRT", covariates = "BASE", visit = "VIS")
135175

136176
expect_error(
137-
gcomp_responder(dat, vars, reference_levels = "Placebo", contrast = "weird"),
177+
gcomp_responder(
178+
dat,
179+
vars,
180+
reference_levels = "Placebo",
181+
contrast = "weird"
182+
),
138183
regexp = "(?i)contrast|allowed|supported|'arg' should be one of"
139184
)
140185
})
@@ -144,10 +189,18 @@ testthat::test_that("gcomp_responder works with no covariates after extraction (
144189
set.seed(4)
145190
dat <- data.frame(
146191
Y = rbinom(60, 1, 0.45),
147-
TRT = factor(sample(c("Placebo","Drug"), 60, TRUE), levels = c("Placebo","Drug")),
192+
TRT = factor(
193+
sample(c("Placebo", "Drug"), 60, TRUE),
194+
levels = c("Placebo", "Drug")
195+
),
148196
AVISIT = "W12"
149197
)
150-
vars <- list(outcome = "Y", group = "TRT", covariates = NULL, visit = "AVISIT")
198+
vars <- list(
199+
outcome = "Y",
200+
group = "TRT",
201+
covariates = NULL,
202+
visit = "AVISIT"
203+
)
151204

152205
out <- gcomp_responder(dat, vars, reference_levels = "Placebo")
153206
expect_true(any(grepl("^lsm_", names(out))))
@@ -158,11 +211,19 @@ testthat::test_that("gcomp_responder_multi applies per-visit and suffixes names"
158211
set.seed(5)
159212
dat <- data.frame(
160213
Y = rbinom(50, 1, 0.5),
161-
TRT = factor(sample(c("Placebo","Drug"), 50, TRUE), levels = c("Placebo","Drug")),
214+
TRT = factor(
215+
sample(c("Placebo", "Drug"), 50, TRUE),
216+
levels = c("Placebo", "Drug")
217+
),
162218
BASE = rnorm(50),
163-
AVISIT = factor(sample(c("W4","W8"), 50, TRUE)) # unsorted by design
219+
AVISIT = factor(sample(c("W4", "W8"), 50, TRUE)) # unsorted by design
220+
)
221+
vars <- list(
222+
outcome = "Y",
223+
group = "TRT",
224+
covariates = "BASE",
225+
visit = "AVISIT"
164226
)
165-
vars <- list(outcome = "Y", group = "TRT", covariates = "BASE", visit = "AVISIT")
166227

167228
out <- gcomp_responder_multi(dat, vars, reference_levels = "Placebo")
168229

@@ -174,5 +235,5 @@ testthat::test_that("gcomp_responder_multi applies per-visit and suffixes names"
174235
}
175236
# Sanity: entries have est/se/df
176237
any_nm <- names(out)[1]
177-
expect_true(all(c("est","se","df") %in% names(out[[any_nm]])))
238+
expect_true(all(c("est", "se", "df") %in% names(out[[any_nm]])))
178239
})

0 commit comments

Comments
 (0)