ggmap, tidy verse: "non-USA countries" with county, municipality, subregion data?

There are several excellent tutorials on using ggmap in combination with tidyverse to present good-looking maps on sub-country level. See e.g., this one:

However, almost all assume we live in the US :frowning:

I'm looking to create a base map with counties/municipaliteis in Sweden (län/kommun) and then do several analysis using "fill=". But I cant find the underlying map data that can then be passed through to various ggplot commands.

Can anybody help?

I don't know anything about Sweden, but a good bet if you're looking for a basemap like this would be to Google something like "sweden county geojson" of "sweden county shapefile". Using that search, I ended up on this site that has county and municipal boundaries available via API -- cool!

Here's an example of how to download those files and read them into R as sf objects which you can then map with ggplot2, tmap, leaflet, etc.

library(sf)
#> Warning: package 'sf' was built under R version 3.6.3
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1

tmp1 <- tempfile()
tmp2 <- tempfile()

download.file("http://api.thenmap.net/v2/se-4/geo/2020-06-03", destfile = tmp1)
download.file("http://api.thenmap.net/v2/se-7/geo/2020-06-03", destfile = tmp2)

county <- read_sf(tmp1)
mun <- read_sf(tmp2)

plot(mun)

plot(county)

Created on 2020-06-03 by the reprex package (v0.3.0)

1 Like

WOW that looks great. thx. I assume I can also read those in with ggmap also? (I'm more familiar with that than the commands you suggest...)

I haven't used ggmap much, but my understanding is that it just produces a ggplot object, so you should be able to add layers. Here's an example of plotting these two layers using ggplot.

library(sf)
library(ggplot2)

tmp1 <- tempfile()
tmp2 <- tempfile()

download.file("http://api.thenmap.net/v2/se-4/geo/2020-06-03", destfile = tmp1)
download.file("http://api.thenmap.net/v2/se-7/geo/2020-06-03", destfile = tmp2)

county <- read_sf(tmp1)
mun <- read_sf(tmp2)

ggplot() +
  geom_sf(data = mun, aes(fill = as.numeric(id))) +
  geom_sf(data = county, fill = NA, color = "red") +
  theme_void()

Created on 2020-06-03 by the reprex package (v0.3.0)

1 Like

Hey Matt, appreciate your input. But there are only 2 variables in the dataframe behind these maps: "id" and "geometry" (see attached pic for "mun"). As I understand it, I need more info if I want to create customize my map (e.g., “fill” them based on my data analysis). It seems I need at least lat/long (X and Y), names of the municipalies, groups, regions, etc). Or am I supposed to convert these polygon files in order to get at that information?

With ggmaps you convert the polygon map info to a dataframe using "map_data" function and then do queries (with tidyverse or whatever) to select certain parts of the map. But not sure with these data. tips?

BTW, I found this site which may be the answer, but unsure what format to bring into R?
https://public.opendatasoft.com/explore/dataset/sverige-kommuner-municipalities-of-sweden/export/

To be more concrete I want to:
. only map "Skåne County" (ignore others)
. only "fill" the (34) municipalities within Skåne County with a color scheme based on my project data.
Thx, Scott

You don't need lat/long points because the geometry column contains all the geographic information R needs to plot the polygons. So then what you are missing here is the names of the counties/municipalities and the data you want to fill the muncipalities with.

According to the documentation of the API that has this Sweden geographies, there is a separate API end point that has data associated with the geojson files. So you can download that data and join it to the sf object that contains the boundaries. From there, you can join by name with each muncipality with your project data to map. Just for an example, I generated some fake data to plot below.

If you want to read a bit more about making maps using sf and ggplot2, this is a good overview.

library(sf)
library(tidyverse)
library(jsonlite)

tmp <- tempfile()
download.file("http://api.thenmap.net/v2/se-7/geo/2020-06-06", destfile = tmp)

mun_name <- fromJSON("http://api.thenmap.net/v2/se-7/data/2020-06-06?language=en&data_props=name|shapeid|is_in") %>% 
  unnest(is_in) %>% 
  rename(county = is_in)

mun <- read_sf(tmp) %>% 
  left_join(mun_name, by = c("id" = "shapeid"))

skåne_mun <- mun %>% 
  filter(county == "Skåne län") %>% 
  mutate(fill_data = rnorm(nrow(.)))

ggplot(skåne_mun) +
  geom_sf(aes(fill = fill_data)) +
  scale_fill_viridis_c() +
  theme_void()

Created on 2020-06-06 by the reprex package (v0.3.0)

1 Like

Matt, this is great, finally got something that I can work with. Two follow ups (see even attached pic)

1 Legend - fill. I can’t figure out how to adjust labels to reflect the units of fill. Perhaps You can simply use your own previous “reprex” to show how to adjust title, unit labels, etc in the legend?

2 Legend - cities. I added cities to the map with geocode and geo_point. But I can’t figure out how to adjust the legend labels. I want to label 4 “medium” and 3 “large” cities … and … display with different size points/colors on map. See my reprex below - can u use this to demonstrate how to add these + appropriate labels?
Thx much

library(ggmap)
library(tidyverse)

# FIRST - add city "large size" 
city_names1 <- c("Malmö", "Lund", "Helsingborg") # big cities.  city4="4" 
locations1 <- geocode(city_names1) # find location of cities 
cities1 <- tibble(name=city_names1, lat=locations1$lat, lon=locations1$lon) # pull them together in a table 

# SECOND - add city "medium size".  
city_names2 <- c("Ängelholm, Sweden", "Trelleborg, Sweden", "Landskrona, Sweden", "Kristianstad, Sweden") # medium cities.  city4="3" 
locations2 <- geocode(city_names2)  # find location of cities 
address=Kristianstad,+Sweden&key=xxx-FhctmI0obuHVFbumw43BPcvLWxQ
cities2 <- tibble(name=c("Ängelholm", "Trelleborg", "Landskrona", "Kristianstad"), 
                  lat=locations2$lat, lon=locations2$lon) # rename more simply.. put in table 

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.