Reputation: 1282
I have a basic map of India with states and borders, some labels, and a number of other specifications stored as a gg object. I'd like to generate a number of maps with a district layer, which will bear data from different variables.
To prevent the district maps overwriting state and country borders, it must be before all the previous code, which I'd like to avoid repeating.
I thought I could do this by calling on $layers
for the gg object as per this answer. However, it throws an error. Reprex is below:
library(ggplot2)
library(sf)
library(raster)
# Download district and state data (should be less than 10 Mb in total)
distSF <- st_as_sf(getData("GADM",country="IND",level=2))
stateSF <- st_as_sf(getData("GADM",country="IND",level=1))
# Add border
countryborder <- st_union(stateSF)
# Basic plot
basicIndia <- ggplot() +
geom_sf(data = stateSF, color = "white", fill = NA) +
geom_sf(data = countryborder, color = "blue", fill = NA) +
theme_dark()
basicIndia
# Data-bearing plot
districts <- ggplot() +
geom_sf(data = distSF, fill = "gold")
basicIndia$layers <- c(geom_sf(data = distSF, fill = "gold"), basicIndia$layers)
basicIndia
#> Error in y$layer_data(plot$data): attempt to apply non-function
Any help would be much appreciated!
Upvotes: 4
Views: 5362
Reputation: 16832
I'm still not sure if I'm missing a detail of what you're looking for, but ggplot2
draws layers in the order you provide them. So something like
ggplot(data) +
geom_col() +
geom_point(...) +
geom_line(...)
will draw columns, then points on top of those, then lines on top of the previous layers.
Same goes for sf
plots, which makes it easy to make a plot like this of multiple geographic levels.
(I'm using rmapshaper::ms_simplify
on the sf
objects just to simplify them and speed things up for plotting.)
library(dplyr)
library(ggplot2)
library(sf)
library(raster)
distSF <- st_as_sf(getData("GADM",country="IND",level=2)) %>% rmapshaper::ms_simplify()
...
Then you can plot by adding up the layers in the order you need them displayed. Keep in mind that if you needed to do other calculations with any of these sf
s, you could do that in advance or inside your geom_sf
.
ggplot() +
geom_sf(data = distSF, fill = "gold", size = 0.1) +
geom_sf(data = stateSF, color = "white", fill = NA) +
geom_sf(data = countryborder, color = "blue", fill = NA)
Regarding trying to add one plot to another: ggplot2
works in layers, so you create a single base ggplot
object, then add geometries on top of it. So you could make, for example, two valid plots:
state_plot <- ggplot(stateSF) +
geom_sf(color = "white", fill = NA)
country_plot <- ggplot(countryborder) +
geom_sf(color = "blue", fill = NA)
But you can't add them, because you would have 2 base ggplot
objects. This should be the error you mentioned:
state_plot +
country_plot
#> Error: Don't know how to add country_plot to a plot
Instead, if you need to make a plot, then add something else on top of it, make the base ggplot
, then add geometry layers, such as a geom_sf
with a different set of data.
state_plot +
geom_sf(data = countryborder, fill = NA, color = "blue")
Created on 2018-10-29 by the reprex package (v0.2.1)
Upvotes: 8
Reputation: 3986
If you look at geom_sf(data=distSF)
you'll see that it is a list made up of two elements - you want the first one which contains the layer information, so geom_sf(data = distSF, fill = "gold")[[1]]
should work.
districts <- ggplot() +
geom_sf(data = distSF, fill = "gold")
basicIndia$layers <- c(geom_sf(data = distSF, fill = "gold")[[1]], basicIndia$layers)
Upvotes: 3