Skip to content

Commit 4d47e86

Browse files
committed
check for incompatible adjustment types
1 parent a3f5170 commit 4d47e86

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed

R/validation-rules.R

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ validate_order <- function(adjustments, type, call = caller_env()) {
1313
return(invisible(orderings))
1414
}
1515

16+
check_incompatible_types(orderings, call)
17+
1618
if (type == "unknown") {
1719
type <- infer_type(orderings)
1820
}
@@ -27,6 +29,24 @@ validate_order <- function(adjustments, type, call = caller_env()) {
2729
invisible(orderings)
2830
}
2931

32+
check_incompatible_types <- function(orderings, call) {
33+
if (all(c("numeric", "probability") %in% orderings$input)) {
34+
numeric_adjustments <- orderings$name[which(orderings$input == "numeric")]
35+
probability_adjustments <- orderings$name[which(orderings$input == "probability")]
36+
cli_abort(
37+
c(
38+
"Can't compose adjustments for different input types.",
39+
"i" = "{cli::qty(numeric_adjustments)}
40+
Adjustment{?s} {.fn {paste0('adjust_', numeric_adjustments)}}
41+
{cli::qty(numeric_adjustments[-1])} operate{?s} on numerics while
42+
{.fn {paste0('adjust_', probability_adjustments)}}
43+
{cli::qty(probability_adjustments[-1])} operate{?s} on probabilities."
44+
),
45+
call = call
46+
)
47+
}
48+
}
49+
3050
check_classification_order <- function(x, call) {
3151
cal_ind <- which(grepl("calibration$", x$name))
3252
eq_ind <- which(grepl("equivocal", x$name))

tests/testthat/_snaps/validation-rules.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,65 @@
8585
Error in `adjust_probability_threshold()`:
8686
! Equivocal zone addition should come after adjustments that update the class probability estimates or hard class predictions.
8787

88+
# validation of adjustments (incompatible types)
89+
90+
Code
91+
tailor() %>% adjust_numeric_calibration() %>% adjust_probability_threshold()
92+
Condition
93+
Error in `adjust_probability_threshold()`:
94+
! Can't compose adjustments for different input types.
95+
i Adjustment `adjust_numeric_calibration()` operates on numerics while `adjust_probability_threshold()` operates on probabilities.
96+
97+
---
98+
99+
Code
100+
tailor() %>% adjust_probability_calibration("logistic") %>%
101+
adjust_probability_threshold(threshold = 0.4) %>% adjust_numeric_range(
102+
lower_limit = 2)
103+
Condition
104+
Error in `adjust_numeric_range()`:
105+
! Can't compose adjustments for different input types.
106+
i Adjustment `adjust_numeric_range()` operates on numerics while `adjust_probability_calibration()` and `adjust_probability_threshold()` operate on probabilities.
107+
108+
---
109+
110+
Code
111+
tailor() %>% adjust_numeric_calibration() %>% adjust_numeric_range(lower_limit = 2) %>%
112+
adjust_probability_threshold(threshold = 0.4)
113+
Condition
114+
Error in `adjust_probability_threshold()`:
115+
! Can't compose adjustments for different input types.
116+
i Adjustments `adjust_numeric_calibration()` and `adjust_numeric_range()` operate on numerics while `adjust_probability_threshold()` operates on probabilities.
117+
118+
---
119+
120+
Code
121+
tailor() %>% adjust_predictions_custom(veg = "potato") %>%
122+
adjust_numeric_calibration() %>% adjust_probability_threshold()
123+
Condition
124+
Error in `adjust_probability_threshold()`:
125+
! Can't compose adjustments for different input types.
126+
i Adjustment `adjust_numeric_calibration()` operates on numerics while `adjust_probability_threshold()` operates on probabilities.
127+
128+
---
129+
130+
Code
131+
tailor() %>% adjust_predictions_custom(veg = "potato") %>%
132+
adjust_probability_calibration("logistic") %>% adjust_probability_threshold(
133+
threshold = 0.4) %>% adjust_numeric_range(lower_limit = 2)
134+
Condition
135+
Error in `adjust_numeric_range()`:
136+
! Can't compose adjustments for different input types.
137+
i Adjustment `adjust_numeric_range()` operates on numerics while `adjust_probability_calibration()` and `adjust_probability_threshold()` operate on probabilities.
138+
139+
---
140+
141+
Code
142+
tailor() %>% adjust_predictions_custom(veg = "potato") %>%
143+
adjust_numeric_calibration() %>% adjust_numeric_range(lower_limit = 2) %>%
144+
adjust_probability_threshold(threshold = 0.4)
145+
Condition
146+
Error in `adjust_probability_threshold()`:
147+
! Can't compose adjustments for different input types.
148+
i Adjustments `adjust_numeric_calibration()` and `adjust_numeric_range()` operate on numerics while `adjust_probability_threshold()` operates on probabilities.
149+

tests/testthat/test-validation-rules.R

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,75 @@ test_that("validation of adjustments (ambiguous type)", {
116116

117117
expect_equal(ambiguous_tailor$type, "unknown")
118118
})
119+
120+
test_that("validation of adjustments (incompatible types)", {
121+
# one bad adjustment each
122+
expect_snapshot(
123+
error = TRUE,
124+
tailor() %>%
125+
adjust_numeric_calibration() %>%
126+
adjust_probability_threshold()
127+
)
128+
129+
# varying the pluralization...
130+
expect_snapshot(
131+
error = TRUE,
132+
tailor() %>%
133+
adjust_probability_calibration("logistic") %>%
134+
adjust_probability_threshold(threshold = .4) %>%
135+
adjust_numeric_range(lower_limit = 2)
136+
)
137+
138+
expect_snapshot(
139+
error = TRUE,
140+
tailor() %>%
141+
adjust_numeric_calibration() %>%
142+
adjust_numeric_range(lower_limit = 2) %>%
143+
adjust_probability_threshold(threshold = .4)
144+
)
145+
146+
# ensure that mixing in ambiguous adjustments doesn't cause issues
147+
expect_snapshot(
148+
error = TRUE,
149+
tailor() %>%
150+
adjust_predictions_custom(veg = "potato") %>%
151+
adjust_numeric_calibration() %>%
152+
adjust_probability_threshold()
153+
)
154+
155+
expect_snapshot(
156+
error = TRUE,
157+
tailor() %>%
158+
adjust_predictions_custom(veg = "potato") %>%
159+
adjust_probability_calibration("logistic") %>%
160+
adjust_probability_threshold(threshold = .4) %>%
161+
adjust_numeric_range(lower_limit = 2)
162+
)
163+
164+
expect_snapshot(
165+
error = TRUE,
166+
tailor() %>%
167+
adjust_predictions_custom(veg = "potato") %>%
168+
adjust_numeric_calibration() %>%
169+
adjust_numeric_range(lower_limit = 2) %>%
170+
adjust_probability_threshold(threshold = .4)
171+
)
172+
173+
expect_no_condition(
174+
tailor() %>%
175+
adjust_predictions_custom(veg = "potato") %>%
176+
adjust_numeric_calibration()
177+
)
178+
179+
expect_no_condition(
180+
tailor() %>%
181+
adjust_numeric_calibration() %>%
182+
adjust_predictions_custom(veg = "potato")
183+
)
184+
185+
expect_no_condition(
186+
tailor() %>%
187+
adjust_probability_threshold(threshold = .4) %>%
188+
adjust_predictions_custom(veg = "potato")
189+
)
190+
})

0 commit comments

Comments
 (0)