Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding ggplot2 geoms to simple features plot

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

test countour map

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
like image 502
juan Avatar asked Jul 10 '17 17:07

juan


People also ask

Which argument of Ggplot can be used to add customization to plots?

To customize the plot, the following arguments can be used: alpha, color, dotsize and fill. Learn more here: ggplot2 dot plot.

What is the difference between Ggplot and ggplot2?

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'.

What operator allows you to keep adding layers to a Ggplot () object?

Elements that are normally added to a ggplot with operator + , such as scales, themes, aesthetics can be replaced with the %+% operator.


1 Answers

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..)).

like image 171
juan Avatar answered Nov 15 '22 05:11

juan