Skip to content

Commit 3cffe34

Browse files
authored
Contour removes duplicates (#5243)
* de-duplicate contours * Add de-duplication test * Add NEWS bullet
1 parent 1d1f795 commit 3cffe34

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

NEWS.md

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

3+
* `stat_contour()` and `stat_contour_filled()` now warn about and remove
4+
duplicated coordinates (@teunbrand, #5215).
35
* `annotation_logticks()` skips drawing ticks when the scale range is non-finite
46
instead of throwing an error (@teunbrand, #5229).
57
* Fixed spurious warnings when the `weight` was used in `stat_bin_2d()`,

R/stat-contour.R

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ StatContour <- ggproto("StatContour", Stat,
9898
params
9999
},
100100

101+
setup_data = function(data, params) {
102+
contour_deduplicate(data)
103+
},
104+
101105
compute_group = function(data, scales, z.range, bins = NULL, binwidth = NULL,
102106
breaks = NULL, na.rm = FALSE) {
103107

@@ -129,6 +133,10 @@ StatContourFilled <- ggproto("StatContourFilled", Stat,
129133
params
130134
},
131135

136+
setup_data = function(data, params) {
137+
contour_deduplicate(data)
138+
},
139+
132140
compute_group = function(data, scales, z.range, bins = NULL, binwidth = NULL, breaks = NULL, na.rm = FALSE) {
133141
breaks <- contour_breaks(z.range, bins, binwidth, breaks)
134142

@@ -352,3 +360,30 @@ pretty_isoband_levels <- function(isoband_levels, dig.lab = 3) {
352360
# and open at their upper boundary
353361
sprintf("(%s, %s]", label_low, label_high)
354362
}
363+
364+
#' De-duplicate data for contours
365+
#'
366+
#' Gives a warning if data has duplicates and throws out duplicated rows.
367+
#'
368+
#' @param data A `data.frame`
369+
#' @param check Column names to check for duplicates
370+
#'
371+
#' @return A de-duplicated `data.frame`
372+
#' @noRd
373+
contour_deduplicate <- function(data, check = c("x", "y", "group", "PANEL")) {
374+
check <- intersect(check, names(data))
375+
if (length(check) == 0) {
376+
return(data)
377+
}
378+
if (vec_duplicate_any(data[, check, drop = FALSE])) {
379+
# We use fromLast here to be consistent with `isoband_z_matrix()` behaviour
380+
dups <- duplicated(data[, check, drop = FALSE], fromLast = TRUE)
381+
data <- data[!dups, , drop = FALSE]
382+
383+
cli::cli_warn(c(
384+
"Contour data has duplicated {.field x}, {.field y} coordinates.",
385+
i = "{sum(dups)} duplicated row{?s} have been dropped."
386+
))
387+
}
388+
data
389+
}

tests/testthat/test-stat-contour.R

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,23 @@ test_that("basic stat_contour_filled() plot builds", {
8080
# implementation in isoband
8181
expect_silent(ggplot_build(p))
8282
})
83+
84+
test_that("stat_contour() removes duplicated coordinates", {
85+
86+
df <- data_frame0(
87+
x = c(1, 1, 2, 2, 1, 1, 2, 2),
88+
y = c(1, 2, 1, 2, 1, 2, 1, 2),
89+
z = c(1, 0, 0, 1, 1, 0, 0, 1),
90+
group = c(1, 1, 1, 1, 2, 2, 2, 2)
91+
)
92+
93+
layer <- stat_contour()
94+
95+
expect_silent(layer$stat$setup_data(df))
96+
expect_warning(
97+
new <- layer$stat$setup_data(transform(df, group = 1)),
98+
"has duplicated"
99+
)
100+
expect_equal(new, df[1:4,], ignore_attr = TRUE)
101+
})
102+

0 commit comments

Comments
 (0)