Skip to contents

This article will show you how to use get_map_data() and {ggplot2} to draw nice looking maps of Denmark.

First we need to load the packages. Here, we only load ggplot2 to minimize dependencies, but you can definitely load the entire tidyverse for convenience.

Getting map data

After loading the required packages we need to get the map data. We will request map data for all (98) danish municipalities. The danish word for municipality is kommune which is what we will request.

municipalities <- get_map_data("kommuner")

In the dropdown below you can see the head() of the data we have received.

head(municipalities)
  #> Simple feature collection with 6 features and 11 fields
  #> Geometry type: MULTIPOLYGON
  #> Dimension:     XY
  #> Bounding box:  xmin: 12.2635 ymin: 55.53633 xmax: 12.73425 ymax: 55.77944
  #> Geodetic CRS:  WGS 84
  #>   dagi_id kode          navn regionskode udenforkommuneinddeling
  #> 1  389103 0101     København        1084                   FALSE
  #> 2  389104 0147 Frederiksberg        1084                   FALSE
  #> 3  389105 0151      Ballerup        1084                   FALSE
  #> 4  389106 0153       Brøndby        1084                   FALSE
  #> 5  389107 0155        Dragør        1084                   FALSE
  #> 6  389108 0157      Gentofte        1084                   FALSE
  #>          regionsnavn              ændret          geo_ændret geo_version
  #> 1 Region Hovedstaden 2024-01-29 22:05:34 2024-01-29 22:05:34          20
  #> 2 Region Hovedstaden 2024-01-16 22:03:35 2024-01-16 22:03:35           7
  #> 3 Region Hovedstaden 2024-01-26 22:04:04 2024-01-26 22:04:04           6
  #> 4 Region Hovedstaden 2024-01-10 22:10:55 2024-01-10 22:10:55           7
  #> 5 Region Hovedstaden 2023-03-24 22:28:38 2023-03-24 22:28:38           3
  #> 6 Region Hovedstaden 2023-03-24 22:28:38 2023-03-24 22:28:38           6
  #>   visueltcenter_x visueltcenter_y                       geometry
  #> 1        12.49391        55.70409 MULTIPOLYGON (((12.54502 55...
  #> 2        12.52373        55.67937 MULTIPOLYGON (((12.53735 55...
  #> 3        12.36852        55.72707 MULTIPOLYGON (((12.30407 55...
  #> 4        12.40438        55.64504 MULTIPOLYGON (((12.44279 55...
  #> 5        12.65023        55.59381 MULTIPOLYGON (((12.64513 55...
  #> 6        12.55072        55.75098 MULTIPOLYGON (((12.59175 55...

The data can then be passed to a ggplot2::geom_sf() to print the map. I have also specified that the fill color should be based on the municipality name to make it a bit more colorful.

ggplot(municipalities, aes(fill = navn)) +
  geom_sf() +
  cowplot::theme_map() +
  theme(legend.position = "none")

Drawing maps with many lines

The above example is not very resource intensive. Trying to plot all the danish voting precincts on the other hand, is somewhat more intensive. To ease the production of such maps, I will now demonstrate how easy it is to simplify the lines (without loss of substantial quality) to faster plot the map. We will use the rmapshaper::ms_simplify() function to do this.

First we get the data with get_map_data() and provide the afstemningsomraader (voting areas) as the type.

voting <- get_map_data("afstemningsomraader")

Then let’s quickly examine how many more polygons we now have to draw.

nrow(municipalities)
#> [1] 99
nrow(voting)
#> [1] 1298

I have printed the amount of polygons for the municipality level as well as the voting precinct level.

To plot all these polygons takes a substantial amount of time - You can either just trust me on that or try it out for yourself after finishing this article!

To accommodate this larger number of polygons we will simplify the lines that make up said polygons.

voting_simplified <- rmapshaper::ms_simplify(
  voting,
  keep = 0.01,
  keep_shapes = TRUE
)

After simplifying the data we can now plot it.

ggplot(voting_simplified, aes(fill = kommunenavn, color = navn)) +
  geom_sf() +
  cowplot::theme_map() +
  theme(legend.position = "none")

Here, I have colored the shapes based on the municipality and then turned the lines of each shape to a different color based on the voting precincts name.

Overlaying multiple maps

If you would like to plot how different municipalities are distributed in the police regions you can simply get the data for both maps and pass them as their own dataset/geom combos in ggplot2.

police <- get_map_data("politikredse")
# We will reuse the municipality data from earlier.

Then you can pass it to ggplot2 as follows.

ggplot() +
  geom_sf(
    data = police,
    aes(fill = navn),
    color = NA
  ) +
  geom_sf(
    data = municipalities,
    color = "black",
    fill = NA
  ) +
  cowplot::theme_map() +
  theme(legend.position = "none")

As you can see, we have now produced a map with shapes from different subsections of Denmark.