Skip to content

Commit f872279

Browse files
edzerkarawoo
authored andcommitted
fix various geom_sf related issues (#2216)
* addresses #2119 * tidy graticule fixes * ggplot2 side of issue r-spatial/sf#396 * tabs -> spaces * add ndiscr to docs * fix #2200 * attempt to fix #2060 All cases were in sf.R a geometry column is address with x$geometry, ggplot2 made the wrong assumption that the geometry column has a fixed name. I replaced this in certain instances, where the data are already pretty transformed and no longer have properties of sf objects, with a fixed position, i.e. x[[1]], which seems to work. * fixes r-spatial/sf#438 * address review comments * fix break on geom_raster, objects without list-column see https://gist.github.com/mdsumner/573ec70014df177baa2d1df7e55e1943 for the case that this PR fixes * tidy up * trying @karawoo's suggestion * adds some sf tests * tidy further
1 parent d870275 commit f872279

File tree

4 files changed

+45
-12
lines changed

4 files changed

+45
-12
lines changed

R/sf.R

+28-11
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@
6161
#' @name ggsf
6262
NULL
6363

64+
geom_column <- function(data) {
65+
w <- which(vapply(data, inherits, TRUE, what = "sfc"))
66+
if (length(w) == 0) {
67+
"geometry" # avoids breaks when objects without geometry list-column are examined
68+
} else {
69+
# this may not be best in case more than one geometry list-column is present:
70+
if (length(w) > 1)
71+
warning("more than one geometry column present: taking the first")
72+
w[[1]]
73+
}
74+
}
75+
76+
is_sf <- function(data) {
77+
inherits(data, "sf")
78+
}
79+
6480
# stat --------------------------------------------------------------------
6581

6682
#' @export
@@ -69,7 +85,7 @@ NULL
6985
#' @format NULL
7086
StatSf <- ggproto("StatSf", Stat,
7187
compute_group = function(data, scales) {
72-
bbox <- sf::st_bbox(data$geometry)
88+
bbox <- sf::st_bbox(data[[ geom_column(data) ]])
7389
data$xmin <- bbox[["xmin"]]
7490
data$xmax <- bbox[["xmax"]]
7591
data$ymin <- bbox[["ymin"]]
@@ -151,7 +167,7 @@ geom_sf <- function(mapping = aes(), data = NULL, stat = "sf",
151167
inherit.aes = TRUE, ...) {
152168

153169
# Automatically determin name of geometry column
154-
if (!is.null(data) && inherits(data, "sf")) {
170+
if (!is.null(data) && is_sf(data)) {
155171
geometry_col <- attr(data, "sf_column")
156172
} else {
157173
geometry_col <- "geometry"
@@ -189,8 +205,9 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
189205
}
190206

191207
for (layer_data in data) {
192-
geometry <- layer_data$geometry
193-
if (is.null(geometry))
208+
if (is_sf(layer_data)) {
209+
geometry <- sf::st_geometry(layer_data)
210+
} else
194211
next
195212

196213
crs <- sf::st_crs(geometry)
@@ -209,18 +226,17 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
209226
return(data)
210227

211228
lapply(data, function(layer_data) {
212-
if (is.null(layer_data$geometry)) {
229+
if (! is_sf(layer_data)) {
213230
return(layer_data)
214231
}
215232

216-
layer_data$geometry <- sf::st_transform(layer_data$geometry, params$crs)
217-
layer_data
233+
sf::st_transform(layer_data, params$crs)
218234
})
219235
},
220236

221237
transform = function(self, data, panel_params) {
222-
data$geometry <- sf_rescale01(
223-
data$geometry,
238+
data[[ geom_column(data) ]] <- sf_rescale01(
239+
data[[ geom_column(data) ]],
224240
panel_params$x_range,
225241
panel_params$y_range
226242
)
@@ -257,13 +273,14 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
257273
# remove tick labels not on axes 1 (bottom) and 2 (left)
258274
if (!is.null(graticule$plot12))
259275
graticule$degree_label[!graticule$plot12] <- NA
260-
276+
261277
sf::st_geometry(graticule) <- sf_rescale01(sf::st_geometry(graticule), x_range, y_range)
262278
graticule$x_start <- sf_rescale01_x(graticule$x_start, x_range)
263279
graticule$x_end <- sf_rescale01_x(graticule$x_end, x_range)
264280
graticule$y_start <- sf_rescale01_x(graticule$y_start, y_range)
265281
graticule$y_end <- sf_rescale01_x(graticule$y_end, y_range)
266-
graticule$degree_label <- lapply(graticule$degree_label, function(x) parse(text = x)[[1]])
282+
if (any(grepl("degree", graticule$degree_label)))
283+
graticule$degree_label <- lapply(graticule$degree_label, function(x) parse(text = x)[[1]])
267284

268285
list(
269286
x_range = x_range,

man/ggsf.Rd

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-function-args.r

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ test_that("geom_xxx and GeomXxx$draw arg defaults match", {
1313
# These aren't actually geoms, or need special parameters and can't be tested this way.
1414
geom_fun_names <- setdiff(
1515
geom_fun_names,
16-
c("geom_map", "geom_sf", "annotation_custom", "annotation_map",
16+
c("geom_map", "geom_sf", "geom_column", "annotation_custom", "annotation_map",
1717
"annotation_raster", "annotation_id")
1818
)
1919

tests/testthat/test-geom-sf.R

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
context("geom-sf")
2+
3+
# Visual tests ------------------------------------------------------------
4+
5+
test_that("geom_sf draws correctly", {
6+
skip_if_not_installed("sf")
7+
8+
f <- system.file("gpkg/nc.gpkg", package="sf")
9+
nc <- sf::read_sf(f)
10+
ggplot() + geom_sf(data = nc)
11+
ggplot() + geom_sf(data = nc) + coord_sf(datum = 4326)
12+
13+
pts <- sf::st_sf(a = 1:2, geometry = sf::st_sfc(sf::st_point(0:1), sf::st_point(1:2)))
14+
ggplot() + geom_sf(data = pts)
15+
})

0 commit comments

Comments
 (0)