The sf
package seems like a much more user-friendly approach to working with spatial data than, say, sp
. For example, if I have a set of latitude/longitude coordinates, I can plot easily with the development version of ggplot2
:
library(sf)
devtools::install_github("tidyverse/ggplot2")
library(ggplot2)
# generate some data
set.seed(123)
y = rnorm(10, mean=40, sd=20)
x = rnorm(10, mean=-100, sd=30)
# collect to data.frame
xy = data.frame(x=x,y=y)
# create sf object
xy.sf = sf::st_as_sf(xy, coords=c("x", "y"), crs=4269)
# plot points
ggplot(data=xy.sf) + geom_sf()
The ggplot2::geom_sf
function knows that the xy.sf
object's geometry is a set of points and so I don't need to invoke, e.g., ggplot2::geom_point()
.
However, suppose I want to add another geom based on the set of points.
For example, if I want to generate a contour layer to show where points are concentrated, I would use ggplot2::geom_density2d
or ggplot2::stat_density2d
, as suggested in this answer and this answer.
However, the following code
ggplot(data=xy.sf) +
geom_sf() +
geom_density2d(data=xy.sf, aes(x=x,y=y,colour=..level..))
produces the following image
Note that the countour lines seem to have coordinates reversed!
I tried fiddling with the above code, but can't get it to work. I realize the sf
package is fairly new, but the map is so close to being right! Any ideas?
Edit: Forgot to add session info
> sessionInfo()
R version 3.4.0 (2017-04-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggplot2_2.2.1.9000 sf_0.4-3
loaded via a namespace (and not attached):
[1] Rcpp_0.12.9 magrittr_1.5 maps_3.1.1 units_0.4-4
[5] MASS_7.3-47 munsell_0.4.3 geosphere_1.5-5 colorspace_1.3-2
[9] lattice_0.20-35 rjson_0.2.15 jpeg_0.1-8 rlang_0.1.1
[13] stringr_1.2.0 udunits2_0.13 plyr_1.8.4 tools_3.4.0
[17] rgdal_1.2-5 grid_3.4.0 gtable_0.2.0 png_0.1-7
[21] DBI_0.5-1 ggthemes_3.3.0 lazyeval_0.2.0 assertthat_0.1
[25] digest_0.6.12 tibble_1.3.1 ggmap_2.6.1 reshape2_1.4.2
[29] mapproj_1.2-4 labeling_0.3 sp_1.2-4 stringi_1.1.2
[33] compiler_3.4.0 RgoogleMaps_1.4.1 scales_0.4.1 proto_1.0.0
To customize the plot, the following arguments can be used: alpha, color, dotsize and fill. Learn more here: ggplot2 dot plot.
You may notice that we sometimes reference 'ggplot2' and sometimes 'ggplot'. To clarify, 'ggplot2' is the name of the most recent version of the package. However, any time we call the function itself, it's just called 'ggplot'.
Elements that are normally added to a ggplot with operator + , such as scales, themes, aesthetics can be replaced with the %+% operator.
For future reference, I thought I'd post my findings as an answer:
It turns out that adding a layer after geom_sf
, e.g., geom_density2d
, does not inherit the mapping aesthetic applied to geom_sf
.
Note that this works as expected:
ggplot(data=xy.sf, aes(x=x, y=y)) +
geom_sf() +
geom_density2d(aes(colour=..level..))
but only because x,y
exist as objects separate from xy.sf
.
Thus, the following throws an error:
rm(x,y)
ggplot(data=xy.sf, aes(x=x, y=y)) +
geom_sf() +
geom_density2d(aes(colour=..level..))
Error in FUN(X[[i]], ...) : object 'x' not found
Of course, this can be found in the documentation!
"
geom_sf
uses a unique aesthetic:geometry
... Unlike other aesthetics,geometry
will never be inherited from the plot."
So the workaround I found is to use the x,y
objects themselves, or a pure data.frame
version of the sf
object; e.g., geom_density2d(data=xy, aes(x,y,colour=..level..))
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With