Skip to content

Commit 88d0517

Browse files
authored
stat_smooth() drops failed groups (#5371)
* Return NULL when fit fails * Add test * Add news bullet * Guarantee clean error in test * Use `try_fetch()`
1 parent fd35a9e commit 88d0517

File tree

4 files changed

+40
-14
lines changed

4 files changed

+40
-14
lines changed

NEWS.md

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

3+
* Failing to fit or predict in `stat_smooth()` now gives a warning and omits
4+
the failed group, instead of throwing an error (@teunbrand, #5352).
5+
36
* `resolution()` has a small tolerance, preventing spuriously small resolutions
47
due to rounding errors (@teunbrand, #2516).
58

R/stat-smooth.R

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,25 @@ StatSmooth <- ggproto("StatSmooth", Stat,
171171
method.args$method <- "REML"
172172
}
173173

174-
model <- inject(method(
175-
formula,
176-
data = data,
177-
weights = weight,
178-
!!!method.args
179-
))
180-
181-
prediction <- predictdf(model, xseq, se, level)
174+
prediction <- try_fetch(
175+
{
176+
model <- inject(method(
177+
formula,
178+
data = data,
179+
weights = weight,
180+
!!!method.args
181+
))
182+
predictdf(model, xseq, se, level)
183+
},
184+
error = function(cnd) {
185+
cli::cli_warn("Failed to fit group {data$group[1]}.", parent = cnd)
186+
NULL
187+
}
188+
)
189+
if (is.null(prediction)) {
190+
return(NULL)
191+
}
192+
182193
prediction$flipped_aes <- flipped_aes
183194
flip_data(prediction, flipped_aes)
184195
},

tests/testthat/test-geom-smooth.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ test_that("default smoothing methods for small and large data sets work", {
7777
expect_equal(plot_data$y, as.numeric(out))
7878
})
7979

80+
test_that("geom_smooth() works when one group fails", {
81+
# Group A fails, B succeeds
82+
df <- data_frame0(
83+
x = c(1, 2, 1, 2, 3),
84+
y = c(1, 2, 3, 2, 1),
85+
g = rep(c("A", "B"), 2:3)
86+
)
87+
p <- ggplot(df, aes(x, y, group = g)) +
88+
geom_smooth(method = "loess", formula = y ~ x)
89+
90+
suppressWarnings(
91+
expect_warning(ld <- layer_data(p), "Failed to fit group 1")
92+
)
93+
expect_equal(unique(ld$group), 2)
94+
expect_gte(nrow(ld), 2)
95+
})
8096

8197
# Visual tests ------------------------------------------------------------
8298

tests/testthat/test-stats.R

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,9 @@ test_that("plot succeeds even if some computation fails", {
55
b1 <- ggplot_build(p1)
66
expect_equal(length(b1$data), 1)
77

8-
p2 <- p1 + geom_smooth()
8+
p2 <- p1 + stat_summary(fun = function(x) stop("Failed computation"))
99

10-
# TODO: These multiple warnings should be summarized nicely. Until this gets
11-
# fixed, this test ignores all the following errors than the first one.
12-
suppressWarnings(
13-
expect_warning(b2 <- ggplot_build(p2), "Computation failed")
14-
)
10+
expect_warning(b2 <- ggplot_build(p2), "Computation failed")
1511
expect_equal(length(b2$data), 2)
1612
})
1713

0 commit comments

Comments
 (0)