-
Notifications
You must be signed in to change notification settings - Fork 293
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
geom_sf() #88
Comments
One thing to keep in mind is that ggplot2 works with data in data.frames. I'm not familiar with sf object and how they are encoded, but this needs to be figured out first (maybe it already is)... |
Thanks - |
Super - that was a quick solve :) You are welcome to open an issue in ggforce if you wish, unless you're planning on a separate |
Thank you, great idea - I opened the issue there. |
I think this should either be included in sf itself or in ggplot2. |
If you want it in ggplot2 I'm fine with moving it over there... |
Maybe develop it in ggforce first, and then decide? |
I'll leave that up to you and Hadley - ggforce probably has a quicker release cycle than ggplot2 (unless Hadley has hired a new intern:)... |
I think it's important enough that I'd do a ggplot2 release specifically for it |
Ok - I'll see if I can get time to make a proof-of-concept implementation of it in a ggplot2 branch instead of ggforce |
Awesome - thanks! |
Sounds great! |
Wrt to coordinate systems, I think it might be to transform each layer to lat/lon coordinates, and then assume the user will use Alternatively it would be possible to have some sort of helper that did: something_sf <- function(sf, ...) {
list(
geom_sf(...),
coord_map(proj = get_projection(sf))
)
} (this is purely imaginary code, but it would mean that the last sf added "wins" the battle of coordinate systems) Doing anything more automatically would require bigger changes to ggplot2 because there's no automatic guessing of coordinate systems. |
Reading |
Datum is what I was missing - thanks! The easiest way to get this to work with ggplot2 would be to have some sort of universal numeric representation of location, but I'm guessing that that doesn't exist. Alternatively, if there was a special vector class that had an attribute we could do something like what we do for POSIXct + time zones at the scale level. Hmmm, if |
There is a great deal of interoperability in different coordinate reference systems (CRS), look for instance at http://spatialreference.org/ref/epsg/4326/ for 14 encodings of datum WGS84. Geodesists and national mapping agencies all over the world work continuously to improve this, but ignore package Package
having I think this is as close as you can get to a universal numeric representation of location, and to the POSIXct + TZ metaphor. |
Does this approach sound reasonable?
This is a bit inefficient because of needless re-projection, but it would make initial ggplot2 implementation simpler (and then in the longer run we could figure out a system where you'd get a default |
Not all spatial data have a CRS: it may be missing, local, or non-Earth related (think astrophysics, cell biology or MRT scan data). I think
Ideally, the projection should happen by (And as a side node: 4267 is not WGS84, but NAD27: a local (North American) Datum) |
There's currently no way for a geom to request a coordinate system, so we have to rely on the user supplying either If we can't always convert to WGS84, then we'll need a new vector class: projected <- function(x, proj4string) {
stopifnot(is.numeric(x))
structure(x, class = "projected", proj4string = proj4string)
} which will be (redundantly) applied to both We'll also need some hacks so that a |
Much of this is beyond my understanding. Do note that you can't reproject x and y independently. |
Yeah, I was just thinking that too. In that case I think the best we can do is give a warning if there are multiple CRSs. Anyway, I think I at least understand the main problems now, and I can keep mulling over what we need to do in ggplot2 to better support spatial data. It feels like ggspatial (or ggsf or whatever we want to call it) could be a good project for another summer intern. |
This sounds more and more like an effort of ggraph scope, which is not something I can take upon me right now. I'll be happy to chime in but I think someone else needs to drive it forward |
While Hadley is thinking about an utopian way to dynamically reproject maps on the fly, we can do something simple now that will make many users happy, by making clear (documented) assumptions:
How does that sound? |
Yeah, we can absolutely start by assuming that all layers are already correctly projected. |
Why do you even need a |
Because |
The current geom_polygon expects one row per vertex. But could it not be made so that if the data is an sf object (or indeed inherits from sf) that it draws polygons using the geometry in each row? I'm not sure putting the name of a class in a geom_name (as geom_sf) is a good idea either. There's no geom_data.frame, and this would seem to violate the grammar inherent in geom function names. Given that a single sf object could contain objects of differing geometries (points, lines and polys) it seems hard to decide on a good name for a geom function that could output such a range of different possible shapes. Also, if I create a class that inherits from How about |
geom_polygon requires at least two rows for a single line and will throw warnings if only a single row is provided. As i understand it sf data are data.frames containing a column with the sf data (I might be totally wrong - haven't got time to look into sf yet). Anyway I see no violation of the grammar as long as a geom requires a specific column class for some of its operations... |
I think you're missing the fundamental difference between sf and sp, and unfortunately there's no way a geom could work in the way you describe. |
First of all @edzer 👍 package. I'm happy to upgrade However, I don't get the fundamental different between
Or can a |
@mtennekes - thanks! The metadata is stored in the attributes of the simple feature geometry list-column, but you get them easiest by Yes, conversion should work for (multi)points, (multi)linestrings and (multi)polygons; in case of |
yes: an |
One of my utopian visions would be to have hierarchical spatial data created by expression in a general grammar. There's a sense in which a the gg aesthetic settings are a select, group by, arrange chain and the plotted geoms could alternatively result in persistent spatial layers. I see real value in an integration of complex object structure and aesthetic mappings, in a way that say a layer in GIS incorporates geometry and aesthetics, but is (usually) stripped back to only geometry or only presentation form when serialized, or published. I don't think that is too utopian, but it requires some deeper integration of "spatial" and "the grammars". Some can already be easily done, for example a table of points measuring animal tracks over time is organizable by straight forward dplyr verbs and the result can be plotted with ggvis, as multi points, or multi-lines, or passed to an sf or sp composer function. The concepts are not radically different, in fact I think they are exactly the same - but the tools are not easily compatible. I've been exploring areas where the two worlds are brought closer, but a fuller system needs wider discussion and involvement. I think there's a very timely opportunity here. |
Is is accurate to say that sf objects (from a single row) come as their own custom stat? Is there any example of geoms like that already? @hadley I also realized that the fortify model would work, as long as we think about it on a per-feature basis, not over whole dataset, the internal decomposition would essentially be the same as that iiuc, though modified for the extra structure in multipolygons, applied to the grob calls. |
I'll repeat a bit from #131, but I think I'd rather have an interface on st_read(system.file("shape/nc.shp", package="sf")) %>%
ggplot(aes(sf=geom, fill=SID79)) +
geom_sf() # or some other name :) That would offer free support for every class that inherits from More complex stuff is also easier to imagine (at least for me): st_read(system.file("shape/nc.shp", package="sf")) %>%
as_tibble() %>% # (sfc does not allow multiple geometries)
mutate(buffer = st_buffer(geometry)) %>%
ggplot() +
geom_sf(geometry, aes(sf=geom, fill=SID79)) +
geom_sf(buffer, aes(sf=geom, fill=NA)) It might also be worthwhile to consider that geometries have multiple representations; this is central to the grammar of graphics. A polygon could be represented by its vertex for instance. Would that be |
For those of you interested in what's happening: there is a working library(sf)
library(maps)
world1 <- st_as_sf(map('world', plot = FALSE, fill = TRUE))
library(ggplot2)
ggplot() + geom_sf(data = world1) and, from the help pages of nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"))
ggplot(nc) + geom_sf(aes(fill = AREA)) Comments are welcome. |
@edzer It ensures all layers have the same CRS (not necessarily WGS84) - that's just used as the datum for the graticule |
Ah, I didn't know you got that far. I now see: library(sf)
library(maps)
library(ggplot2)
world1 <- sf::st_as_sf(map('world', plot = FALSE, fill = TRUE))
world2 <- st_transform(world1,
"+proj=laea +y_0=0 +lon_0=155 +lat_0=-90 +ellps=WGS84 +no_defs")
ggplot() + geom_sf(data = world2) where we need to revisit the tick labels, but otherwise: nice! |
Very promising! |
In the circular world example of #88 the graticule is no longer clipped by the graph box; the original st_graticule tried to do this. It now returns a global graticule, and transforms that; the axis tick values and labels for that case no longer make sense. This commit changes these into "." for this particular case, so they're not longer overplotted by ggplot (they still show as a ".", though).
@GreenStat could you please file the line and point issues individually on ggplot2? @edzer I think we can now close this issue |
Sorry to chime in in this now-closed issue (from which I learned a lot), but I have a fast question. I did not exactly understand what What if multiple |
Dear all, I am plotiing values in attribute table of a shapefile and the values in one of the table ( e.g. Duration) ranges from 0-4370 and i want to classfy them into 5 using somthing like breaks, Is there any way to to do this classfication in r;
Best regards, Solomon |
Create a new factor variable by cutting on those breaks and plot that:
I've specified a fill and colour aesthetic otherwise the legend symbols don't get drawn properly. There's probably a way of making the legend draw as dots, but you've probably got polygons so adjust as needed... Use the |
Error: Object is neither from class sf, stars, Spatial, nor Raster. I have merged two dataframes. One of them had long,lat and the other one had geom for Africa. However, no matter what I do, I got the error saying "Error: Object is neither from class sf, stars, Spatial, nor Raster. I am trying to use geom_sf and tm for mapping. None of them worked. |
Maybe it is a data.frame. Have you tried passing it to |
We need a
geom_sf()
to render simple feature objects in ggplots, e.g. wherewould add the polygon boundaries, and further argument can alter the color of polygons and polygon boundaries, as well as point and line geometries. I wrote some building blocks, basically functions that convert
sf
objects into grid grobs here and am willing to help out, but would appreciate some help getting started from someone who's been here before: @thomasp85, @hadley, @mdsumner , @hrbrmstr?Issues to keep in mind:
geom_sf
control the aspect ratio used, such that 1 km north equals 1 km east?st_transform
?geom_sf
s, can we verify that coordinate reference systems correspond?The text was updated successfully, but these errors were encountered: