Skip to content

Commit 48660e1

Browse files
microlyclauswilke
authored andcommitted
Enable geom_sf to automatically determine the legend type (#3646)
* automatically determine the legend type * add tests * add news item
1 parent 16ed4d0 commit 48660e1

File tree

5 files changed

+79
-4
lines changed

5 files changed

+79
-4
lines changed

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# ggplot2 (development version)
22

3+
* `geom_sf()` now determines the legend type automatically (@microly, #3646).
4+
35
* `scale_x_continuous()` and `scale_y_continuous()` gains an `n.breaks` argument
46
guiding the number of automatic generated breaks (@thomasp85, #3102)
57

R/geom-sf.R

+1-2
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,10 @@ geom_sf <- function(mapping = aes(), data = NULL, stat = "sf",
197197
mapping = mapping,
198198
stat = stat,
199199
position = position,
200-
show.legend = if (is.character(show.legend)) TRUE else show.legend,
200+
show.legend = show.legend,
201201
inherit.aes = inherit.aes,
202202
params = list(
203203
na.rm = na.rm,
204-
legend = if (is.character(show.legend)) show.legend else "polygon",
205204
...
206205
)
207206
),

R/layer-sf.R

+23
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@ LayerSf <- ggproto("LayerSf", Layer,
3535
self$mapping$geometry <- as.name(geometry_col)
3636
}
3737
}
38+
39+
# automatically determine the legend type
40+
if (is.na(self$show.legend) || isTRUE(self$show.legend)) {
41+
if (is_sf(data)) {
42+
sf_type <- detect_sf_type(data)
43+
if (sf_type == "point") {
44+
self$geom_params$legend <- "point"
45+
} else if (sf_type == "line") {
46+
self$geom_params$legend <- "line"
47+
} else {
48+
self$geom_params$legend <- "polygon"
49+
}
50+
}
51+
} else if (is.character(self$show.legend)) {
52+
self$geom_params$legend <- self$show.legend
53+
self$show.legend <- TRUE
54+
}
3855
data
3956
}
4057
)
@@ -62,3 +79,9 @@ is_sf <- function(data) {
6279
#' @export
6380
scale_type.sfc <- function(x) "identity"
6481

82+
# helper function to determine the geometry type of sf object
83+
detect_sf_type <- function(sf) {
84+
geometry_type <- unique(as.character(sf::st_geometry_type(sf)))
85+
if (length(geometry_type) != 1) geometry_type <- "GEOMETRY"
86+
sf_types[geometry_type]
87+
}

R/stat-sf.R

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ stat_sf <- function(mapping = NULL, data = NULL, geom = "rect",
2828
mapping = mapping,
2929
geom = geom,
3030
position = position,
31-
show.legend = if (is.character(show.legend)) TRUE else show.legend,
31+
show.legend = show.legend,
3232
inherit.aes = inherit.aes,
3333
params = list(
3434
na.rm = na.rm,
35-
legend = if (is.character(show.legend)) show.legend else "polygon",
3635
...
3736
)
3837
)

tests/testthat/test-geom-sf.R

+52
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,57 @@
11
context("geom-sf")
22

3+
test_that("geom_sf() determines the legend type automatically", {
4+
skip_if_not_installed("sf")
5+
if (packageVersion("sf") < "0.5.3") skip("Need sf 0.5.3")
6+
7+
mp <- sf::st_sf(
8+
geometry = sf::st_sfc(sf::st_multipoint(rbind(c(1,1), c(2,2), c(3,3)))),
9+
v = "a")
10+
11+
s1 <- rbind(c(0,3),c(0,4),c(1,5),c(2,5))
12+
s2 <- rbind(c(0.2,3), c(0.2,4), c(1,4.8), c(2,4.8))
13+
s3 <- rbind(c(0,4.4), c(0.6,5))
14+
15+
mls <- sf::st_sf(
16+
geometry = sf::st_sfc(sf::st_multilinestring(list(s1,s2,s3))),
17+
v = "a")
18+
19+
p1 <- rbind(c(0,0), c(1,0), c(3,2), c(2,4), c(1,4), c(0,0))
20+
p2 <- rbind(c(1,1), c(1,2), c(2,2), c(1,1))
21+
p3 <- rbind(c(3,0), c(4,0), c(4,1), c(3,1), c(3,0))
22+
p4 <- rbind(c(3.3,0.3), c(3.8,0.3), c(3.8,0.8), c(3.3,0.8), c(3.3,0.3))[5:1,]
23+
p5 <- rbind(c(3,3), c(4,2), c(4,3), c(3,3))
24+
25+
mpol <- sf::st_sf(
26+
geometry = sf::st_sfc(sf::st_multipolygon(list(list(p1,p2), list(p3,p4), list(p5)))),
27+
v = "a")
28+
29+
fun_geom_sf <- function(sf, show.legend) {
30+
p <- ggplot() + geom_sf(aes(colour = v), data = sf, show.legend = show.legend)
31+
ggplot_build(p)
32+
}
33+
34+
# test the automatic choice
35+
expect_identical(fun_geom_sf(mp, TRUE)$plot$layers[[1]]$show.legend, TRUE)
36+
expect_identical(fun_geom_sf(mp, TRUE)$plot$layers[[1]]$geom_params$legend, "point")
37+
38+
expect_identical(fun_geom_sf(mls, TRUE)$plot$layers[[1]]$show.legend, TRUE)
39+
expect_identical(fun_geom_sf(mls, TRUE)$plot$layers[[1]]$geom_params$legend, "line")
40+
41+
expect_identical(fun_geom_sf(mpol, TRUE)$plot$layers[[1]]$show.legend, TRUE)
42+
expect_identical(fun_geom_sf(mpol, TRUE)$plot$layers[[1]]$geom_params$legend, "polygon")
43+
44+
# test that automatic choice can be overridden manually
45+
expect_identical(fun_geom_sf(mp, "point")$plot$layers[[1]]$show.legend, TRUE)
46+
expect_identical(fun_geom_sf(mp, "point")$plot$layers[[1]]$geom_params$legend, "point")
47+
48+
expect_identical(fun_geom_sf(mls, "point")$plot$layers[[1]]$show.legend, TRUE)
49+
expect_identical(fun_geom_sf(mls, "point")$plot$layers[[1]]$geom_params$legend, "point")
50+
51+
expect_identical(fun_geom_sf(mpol, "point")$plot$layers[[1]]$show.legend, TRUE)
52+
expect_identical(fun_geom_sf(mpol, "point")$plot$layers[[1]]$geom_params$legend, "point")
53+
})
54+
355
test_that("geom_sf() removes rows containing missing aes", {
456
skip_if_not_installed("sf")
557
if (packageVersion("sf") < "0.5.3") skip("Need sf 0.5.3")

0 commit comments

Comments
 (0)