Skip to content

Commit e880f74

Browse files
zdz2101ddsjoberg
andauthored
Closes #10 add ard_vif() (#61)
**What changes are proposed in this pull request?** added `ard_vif()` which is essentially a wrapper for `car::vif()` put into our ard structure Provide more detail here as needed. **Reference GitHub issue associated with pull request.** _e.g., 'closes #<issue number>'_ -------------------------------------------------------------------------------- Pre-review Checklist (if item does not apply, mark is as complete) - [x] **All** GitHub Action workflows pass with a ✅ - [x] PR branch has pulled the most recent updates from master branch: `usethis::pr_merge_main()` - [x] If a bug was fixed, a unit test was added. - [x] Code coverage is suitable for any new functions/features (generally, 100% coverage for new code): `devtools::test_coverage()` - [x] Request a reviewer Reviewer Checklist (if item does not apply, mark is as complete) - [x] If a bug was fixed, a unit test was added. - [x] Run `pkgdown::build_site()`. Check the R console for errors, and review the rendered website. - [x] Code coverage is suitable for any new functions/features: `devtools::test_coverage()` When the branch is ready to be merged: - [ ] Update `NEWS.md` with the changes from this pull request under the heading "`# cards (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). - [x] **All** GitHub Action workflows pass with a ✅ - [ ] Approve Pull Request - [ ] Merge the PR. Please use "Squash and merge" or "Rebase and merge". --------- Signed-off-by: Daniel Sjoberg <danield.sjoberg@gmail.com> Signed-off-by: Zelos Zhu <zelos.zhu@atorusresearch.com> Co-authored-by: Daniel Sjoberg <danield.sjoberg@gmail.com>
1 parent 11e4150 commit e880f74

File tree

7 files changed

+212
-0
lines changed

7 files changed

+212
-0
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export(ard_regression)
2222
export(ard_regression_basic)
2323
export(ard_smd)
2424
export(ard_ttest)
25+
export(ard_vif)
2526
export(ard_wilcoxtest)
2627
export(contains)
2728
export(ends_with)

R/ard_vif.R

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#' Regression VIF ARD
2+
#'
3+
#' @description
4+
#' Function takes a regression model object and returns the variance inflation factor (VIF)
5+
#' using [`car::vif()`] and converts it to a ARD structure
6+
#'
7+
#' @param x regression model object
8+
#' See car::vif() for details
9+
#'
10+
#' @param ... arguments passed to `car::vif(...)`
11+
#'
12+
#' @return data frame
13+
#' @name ard_vif
14+
#' @rdname ard_vif
15+
#' @export
16+
#'
17+
#' @examples
18+
#' lm(AGE ~ ARM + SEX, data = cards::ADSL) |>
19+
#' ard_vif()
20+
ard_vif <- function(x, ...) {
21+
# check inputs ---------------------------------------------------------------
22+
check_not_missing(x)
23+
24+
vif <- cards::eval_capture_conditions(car::vif(x, ...))
25+
26+
# if vif failed, set result as NULL, error will be kept through eval_capture_conditions()
27+
if (is.null(vif$result)) {
28+
# try to capture variable names from `terms()`
29+
lst_terms <- cards::eval_capture_conditions(attr(stats::terms(x), "term.labels"))
30+
# we cannot get variable names, error out
31+
if (!is.null(lst_terms[["error"]])) {
32+
cli::cli_abort(
33+
c("There was an error running {.fun car::vif}. See below.", x = vif[["error"]])
34+
)
35+
}
36+
vif$result <- dplyr::tibble(
37+
variable = lst_terms[["result"]],
38+
VIF = list(NULL),
39+
GVIF = list(NULL),
40+
aGVIF = list(NULL),
41+
df = list(NULL)
42+
)
43+
}
44+
# if VIF is returned
45+
else if (!is.matrix(vif$result)) {
46+
vif$result <- dplyr::tibble(variable = names(vif$result), VIF = vif$result)
47+
}
48+
# if Generalized VIF is returned
49+
else if (is.matrix(vif$result)) {
50+
vif$result <-
51+
vif$result |>
52+
as.data.frame() %>%
53+
dplyr::mutate(., variable = rownames(.), .before = 1L) |>
54+
dplyr::rename(
55+
aGVIF = "GVIF^(1/(2*Df))",
56+
df = "Df"
57+
) |>
58+
dplyr::tibble()
59+
}
60+
61+
# Clean-up the result to fit the ard structure through pivot
62+
vif$result <-
63+
vif$result |>
64+
tidyr::pivot_longer(
65+
cols = -c("variable"),
66+
names_to = "stat_name",
67+
values_to = "stat"
68+
) |>
69+
dplyr::mutate(
70+
context = "vif",
71+
stat_label = ifelse(
72+
.data$stat_name == "aGVIF",
73+
"Adjusted GVIF",
74+
.data$stat_name
75+
),
76+
fmt_fn = map(
77+
.data$stat,
78+
function(.x) {
79+
# styler: off
80+
if (is.integer(.x)) return(0L)
81+
if (is.numeric(.x)) return(1L)
82+
# styler: on
83+
NULL
84+
}
85+
)
86+
)
87+
88+
# Bind the results and possible warning/errors together
89+
vif_return <- dplyr::tibble(
90+
vif$result,
91+
warning = vif["warning"],
92+
error = vif["error"]
93+
)
94+
95+
# Clean up return object
96+
vif_return |>
97+
cards::tidy_ard_column_order() %>%
98+
{structure(., class = c("card", class(.)))} # styler: off
99+
}

_pkgdown.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ reference:
4242
- ard_regression
4343
- ard_regression_basic
4444
- ard_smd
45+
- ard_vif
4546

4647
- title: "Helpers"
4748
- contents:

inst/WORDLIST

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Lifecycle
99
McNemar's
1010
Newcombe
1111
Su
12+
VIF
1213
XG
1314
Xin
1415
agresti
@@ -18,6 +19,7 @@ funder
1819
jeffreys
1920
pearson
2021
strat
22+
vif
2123
wald
2224
waldcc
2325
wilson

man/ard_vif.Rd

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/ard_vif.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# ard_vif() works
2+
3+
Code
4+
as.data.frame(ard_vif(lm(AGE ~ ARM + SEX, data = cards::ADSL)))
5+
Output
6+
variable context stat_name stat_label stat fmt_fn warning error
7+
1 ARM vif GVIF GVIF 1.015675 1 NULL NULL
8+
2 ARM vif df df 2.000000 1 NULL NULL
9+
3 ARM vif aGVIF Adjusted GVIF 1.003896 1 NULL NULL
10+
4 SEX vif GVIF GVIF 1.015675 1 NULL NULL
11+
5 SEX vif df df 1.000000 1 NULL NULL
12+
6 SEX vif aGVIF Adjusted GVIF 1.007807 1 NULL NULL
13+
14+
---
15+
16+
Code
17+
as.data.frame(ard_vif(lm(AGE ~ BMIBL + EDUCLVL, data = cards::ADSL)))
18+
Output
19+
variable context stat_name stat_label stat fmt_fn warning error
20+
1 BMIBL vif VIF VIF 1.010522 1 NULL NULL
21+
2 EDUCLVL vif VIF VIF 1.010522 1 NULL NULL
22+
23+
# ard_vif() appropriate errors are given for model with only 1 term
24+
25+
Code
26+
as.data.frame(ard_vif(lm(AGE ~ ARM, data = cards::ADSL)))
27+
Output
28+
variable context stat_name stat_label stat fmt_fn warning
29+
1 ARM vif VIF VIF NULL NULL NULL
30+
2 ARM vif GVIF GVIF NULL NULL NULL
31+
3 ARM vif aGVIF Adjusted GVIF NULL NULL NULL
32+
4 ARM vif df df NULL NULL NULL
33+
error
34+
1 model contains fewer than 2 terms
35+
2 model contains fewer than 2 terms
36+
3 model contains fewer than 2 terms
37+
4 model contains fewer than 2 terms
38+
39+
# ard_vif() issues friendly messaging for incorrect object passed in/can't get terms of model
40+
41+
Code
42+
ard_vif(cards::ADSL)
43+
Condition
44+
Error in `ard_vif()`:
45+
! There was an error running `car::vif()`. See below.
46+
x no applicable method for 'vcov' applied to an object of class "c('tbl_df', 'tbl', 'data.frame')"
47+

tests/testthat/test-ard_vif.R

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
test_that("ard_vif() works", {
2+
expect_snapshot(
3+
lm(AGE ~ ARM + SEX, data = cards::ADSL) |>
4+
ard_vif() |>
5+
as.data.frame()
6+
)
7+
8+
expect_snapshot(
9+
lm(AGE ~ BMIBL + EDUCLVL, data = cards::ADSL) |>
10+
ard_vif() |>
11+
as.data.frame()
12+
)
13+
})
14+
15+
test_that("ard_vif() appropriate errors are given for model with only 1 term", {
16+
expect_snapshot(
17+
lm(AGE ~ ARM, data = cards::ADSL) |>
18+
ard_vif() |>
19+
as.data.frame()
20+
)
21+
expect_equal(
22+
lm(AGE ~ ARM, data = cards::ADSL) |>
23+
ard_vif() |>
24+
dplyr::select(error) |>
25+
unlist() |>
26+
unique(),
27+
"model contains fewer than 2 terms"
28+
)
29+
})
30+
31+
32+
test_that("ard_vif() issues friendly messaging for incorrect object passed in/can't get terms of model", {
33+
expect_snapshot(
34+
error = TRUE,
35+
cards::ADSL |> ard_vif()
36+
)
37+
})

0 commit comments

Comments
 (0)