-
Notifications
You must be signed in to change notification settings - Fork 2.1k
WIP: sf-ify regular layers #3655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
In ggspatial I implemented this as a Stat...not sure if that's the best way to go, but it might help to look at the code here: https://github.com/paleolimbot/ggspatial/blob/master/R/geom-spatial.R#L162 . Usage is for that is more stat-like: library(ggplot2)
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
df <- data.frame(
lat = 35.76667,
long = -78.63333,
name = "Raleigh"
)
# as a stat
ggplot(df, aes(x = long, y = lat)) +
geom_sf(data = nc, size = 0.1, fill = "white", inherit.aes = FALSE) +
geom_point(stat = ggspatial:::StatSpatialIdentity) +
geom_text(aes(label = name), stat = ggspatial:::StatSpatialIdentity, hjust = -.1, vjust = 1.1) +
coord_sf(crs = 2264)
#> Assuming crs = 4326 in stat_spatial_identity()
#> Assuming crs = 4326 in stat_spatial_identity() # as with_sf()
with_sf <- function(layer, crs = NULL) {
layer$stat <- ggspatial:::create_spatial_stat_class(
layer$stat,
ggplot2:::snake_class(layer$stat)[1]
)
layer$stat$crs <- crs
layer
}
ggplot(df, aes(x = long, y = lat)) +
geom_sf(data = nc, size = 0.1, fill = "white", inherit.aes = FALSE) +
with_sf(geom_point()) +
with_sf(geom_text(aes(label = name), hjust = -.1, vjust = 1.1)) +
coord_sf(crs = 2264)
#> Assuming crs = 4326 in stat_identity()
#> Assuming crs = 4326 in stat_identity() Created on 2019-12-04 by the reprex package (v0.2.1) |
One thing I can see that is missing from the |
@paleolimbot Since we don't have a good way of chaining stats, I'm not sure that using a stat just for the purpose of a coordinate transformation is the right way to go. Also not sure how that would play out with geoms such as @markpayneatwork Yes, of course. This is a work in progress. Source crs can be specified now. library(ggplot2)
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
df <- data.frame(
lat = 35.76667,
long = -78.63333,
name = "Raleigh"
)
ggplot(df, aes(x = long, y = lat)) +
geom_sf(data = nc, size = 0.1, fill = "white", inherit.aes = FALSE) +
with_sf(
geom_point(),
geom_text(aes(label = name), hjust = -.1, vjust = 1.1)
) +
coord_sf(crs = 2264) # transformed data
df_trans <- data.frame(
lat = 734165.51156997,
long = 2108774.28357641,
name = "Raleigh"
)
ggplot(df_trans, aes(x = long, y = lat)) +
geom_sf(data = nc, size = 0.1, fill = "white", inherit.aes = FALSE) +
with_sf(
geom_point(),
geom_text(aes(label = name), hjust = -.1, vjust = 1.1),
crs = 2264
) +
coord_sf(crs = 2264) Created on 2019-12-04 by the reprex package (v0.3.0) |
Thinking some more about this, I don't think a stat can do this. library(ggplot2)
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
ggplot(nc) +
geom_sf(size = 0.1, fill = "white") +
with_sf(
geom_hline(yintercept = 34:36),
geom_vline(xintercept = c(-84, -80, -76))
) +
coord_sf(crs = 2264) Created on 2019-12-04 by the reprex package (v0.3.0) |
Or this. library(ggplot2)
library(readr)
library(ggforce)
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
df <- read_csv(file = "name,population,lat,long
Charlotte,827097,35.227,-80.843
Raleigh,451066,35.772,-78.639
Greensboro,285342,36.073,-79.792
Durham,257636,35.994,-78.899
Winston-Salem,241218,36.1,-80.244")
ggplot(df, aes(x = long, y = lat)) +
geom_sf(data = nc, size = 0.1, fill = "white", inherit.aes = FALSE) +
with_sf(
geom_point(),
geom_mark_hull()
) +
coord_sf(crs = 2264) Created on 2019-12-04 by the reprex package (v0.3.0) |
Fix #3653. library(ggplot2)
library(sf)
#> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
ggplot() +
with_sf(
annotation_map(map_data("state"), fill="antiquewhite", colour="darkgrey")
) +
geom_sf(data = nc) +
coord_sf(crs = st_crs(3347)) Created on 2019-12-04 by the reprex package (v0.3.0) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@hadley Are you Ok with this addition to the grammar? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Is it possible to let ggplot(df, aes(x = long, y = lat)) +
geom_sf(data = nc, size = 0.1, fill = "white", inherit.aes = FALSE) +
geom_point() +
geom_text(aes(label = name), hjust = -.1, vjust = 1.1) +
coord_sf(crs = 2264, transform_non_sf_layers = TRUE) I feel (I don't mean to say this is unacceptable, but it's probably depends on how common this |
@yutannihilation The problem I see is that the Lines 43 to 58 in 913e936
So you'd have to first transform all incoming sf layers to long-lat or similar in |
If we assume most of the usage of non-sf layers are for annotation, this step might not be necessary, but your explanation makes sense, thanks. Hmm... |
Another way to think about the problem: The current |
Just a quick vote that I think |
Thanks for the suggestion, Dewey. This may work, though I foresee some issues with limits. In what CRS would they be specified? Do we need a third parameter, |
It's a hard one for sure...I think it would be impossible for scales to be in anything except final projected coordinates, although the coord |
IIRC my original intention was for other layers to be automatically transformed, assuming that the coordinates were specified in lat and long, and this is supported by one of the examples: ggplot(nc) +
geom_sf() +
annotate("point", x = -80, y = 35, colour = "red", size = 4) I'd really prefer if we could perform this transformation automatically — but I don't know enough about the constraints to know whether or not this is possible. |
@hadley I think the main constraint is the API: We'd have to add an argument to the |
Oh, and it's also a breaking change for any code currently in existence that mixes |
@clauswilke I think those breakages should be minor, and would be worth it (esp since I'm pretty sure that this is what I always intended) |
@hadley Ok, let me take a stab at this and then we can see what it looks like. |
@hadley It turns out changing the Thus, the only other alternative I see is to transform everything to a common CRS first and then transform a second time right before drawing. Maybe I'll take a stab at that to see where it leads. |
What is about that with_sf works with data? Like: ggplot() + In essence, it is a issue about transforming data, so we can only wrap the data... |
Would it be possible to use a Also, I think |
Thanks @paleolimbot, I think your comment just cut the Gordian knot. We can continue treating geometry objects as we currently do, no change required, and we adopt the convention that regular position data is in long-lat (to be configurable in |
I'm glad! I think in |
@paleolimbot See #3659. |
Closing this as it has been superseded by #3659. |
First attempt at implementing the idea proposed in #3654.
Created on 2019-12-04 by the reprex package (v0.3.0)