Reputation: 11
I've been having quite a headache displaying spatial data with ggmap. My very simple goal is to display a choropleth map of California Counties filled with a color ramp that represents integer values associated with each county over a satellite imagery basemap. My initial approach was to map an sf object containing county polygons via geom_sf() over a basemap acquired through the get_googlemap() function, but no matter what I did to the CRS of the sf object, the two images were badly misaligned. After lots of investigation into this issue I discovered that using the SpatialPolygonsDataFrame format mapped much more accurately onto the basemap. If you can help me solve this alignment issue without transforming my data into SpatialPolygonsDataFrames, I can circumvent the next problem entirely.
So, I've converted my objects using as_Spatial, but now, I'm unable to produce the choropleth. When I try to fill by the attribute containing the integers of interest, ggmap will not recognize the attribute and returns the error 'object not found'
In this example, I've used a stamen basemap instead of a google satellite basemap to increase reproducibility.
library(sf)
library(ggmap)
library(tigris)
options(tigris_use_cache = TRUE)
Counties.sf <- counties(state = "CA", cb = TRUE, resolution = "20m", year = 2016)
Counties.sf$Freq <- sample(10, size=nrow(Counties.sf), replace=TRUE) #assign random #s 1-10 to each county in place of my real data
Counties.sf <- st_transform(Counties.sf, 4326) #set correct CRS
bbox.sf<-unname(st_bbox(Counties.sf)) #create bbox for basemap
my.stamen<- get_stamenmap(bbox=bbox.sf, maptype='terrain-background', zoom=8) #call basemap here
Here is how I plot the sf object, filling polygons based on the value in the 'Freq' column
ggmap(my.stamen) +
geom_sf(data=Counties.sf, aes(fill=factor(Freq)), color='black', inherit.aes = FALSE)
1 [sf choropleth]
If you plot the same data without fill, you can clearly see the map alignment issue
ggmap(my.stamen) +
geom_sf(data=Counties.sf, fill=NA, color='black', inherit.aes = FALSE)
2 [sf empty]
So, I've discovered transforming to SpatialPolygonsDataframe helps alignment
Counties.sp<-as_Spatial(Counties.sf)
ggmap(my.stamen)+
geom_polygon(data=Counties.sp, aes(x=long, y=lat, group=group), color='black', fill=NA)
3 [sp empty]
But, when I try to fill the polygons based on the "Freq" column, the error shows object not found
ggmap(my.stamen)+
geom_polygon(data=Counties.sp, aes(x=long, y=lat, group=group, fill=factor(Freq)))
Thoughts? Workarounds? Is there another data format I should try?
Upvotes: 0
Views: 131
Reputation: 11
Thanks,
I was directed to this link which directed me to the answer.
I should use
fortify(Counties.sp, region='NAME')
to transform the sp object to a dataframe containing a row for each vertex grouped by the county name. Then merge the relevant data from the Freq column such that each vertex of a county is assigned to the same Freq value:
merge(merged.df1, Counties.sp@data, by.x='id', by.y='NAME')`
Then you can use geom_polygon()
without issue, so long as aes()
is set equal to the mapping parameter:
ggmap(my.stamen) + geom_polygon(merged.df, mapping=aes(x=long, y=lat, fill=factor(Freq), group=group))
Upvotes: 1