Create maps in R in 10 (fairly) easy steps

Sure you can use this technique for election maps — but it’s also handy for sales figures, mobile data coverage and many other types of data.

Step 8: Add palettes for a multi-layer map

Let's look at the GOP results in South Carolina among the top three candidates. I won't go over the data wrangling on this, except to say that I downloaded results from the South Carolina State Election Commission as well as Census Bureau data for education levels by county. If you download the project files, you'll see the initial data as well as the R code I used to add candidate vote percentages and join all that data to the South Carolina shapefile. That creates a geospatial object scmap to map.

There's so much data for a multi-candidate race that it's a little more complicated to choose what to color beyond "who won." I decided to go with one map layer to show the winner in each county, one layer each for the top three candidates (Trump, Rubio and Cruz) and a final layer showing percent of adult population with at least a bachelor's degree (Why education? Some news reports out of South Carolina said that seemed to correlate with levels of Trump's support; mapping that will help show such a trend.)

In making my color palettes, I decided to use the same numerical scale for all three candidates. If I scaled color intensity for each candidate's minimum and maximum, a candidate with 10% to 18% would have a map with the same color intensities as one who had 45% to 52%, which gives a wrong impression of the losing candidate's strength. So, first I calculated the minimum and maximum for the combined Trump/Rubio/Cruz county results:

minpct <- min(c(scmap$`Donald J TrumpPct`, scmap$`Marco RubioPct` , scmap$`Ted CruzPct`))
maxpct <- max(c(scmap$`Donald J TrumpPct`, scmap$`Marco RubioPct` , scmap$`Ted CruzPct`))

Now I can create a palette for each candidate using different colors but the same intensity range.

trumpPalette <- colorNumeric(palette = "Purples", domain=c(minpct, maxpct))
rubioPalette <- colorNumeric(palette = "Reds", domain = c(minpct, maxpct))
cruzPalette <- colorNumeric(palette = "Oranges", domain = c(minpct, maxpct))

I'll also add palettes for the winner and education layers:

winnerPalette <- colorFactor(palette=c("#984ea3", "#e41a1c"), domain = scmap$winner)
edPalette <- colorNumeric(palette = "Blues", domain=scmap@data$PctCollegeDegree)

Finally, I'll create a basic pop-up showing the county name, who won, the percentage for each candidate and percent of population with a college degree:

scpopup <- paste0("County: ", scmap@data$County,
"Winner: ", scmap@data$winner,
"Trump: ", percent(scmap@data$`Donald J TrumpPct`),
"Rubio: ", percent(scmap@data$`Marco RubioPct`),
"Cruz: ", percent(scmap@data$`Ted CruzPct`),
"Pct w college ed: ", scmap@data$PctCollegeDegree, "% vs state-wide avg of 25%")

This shows a basic map of winners by county:

leaflet(scmap) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addPolygons(stroke=TRUE,
              weight=1,
              smoothFactor = 0.2,
              fillOpacity = .75,
              popup=scpopup, 
              color= ~winnerPalette(scmap@data$winner),
              group="Winners"
 ) %>%
    addLegend(position="bottomleft", colors=c("#984ea3", "#e41a1c"), labels=c("Trump", "Rubio"))
Another basic interactive map, this one with data on more than two candidates.

Step 9: Add map layers and controls

A multi-layer map with layer controls starts off the same as our previous map, with one addition: A group name. In this case, each layer will be its own group, but it's also possible to turn multiple layers on and off together.

The next step is to add additional polygon layers for each candidate and a final layer for college education, along with a layer control to wrap up the code. This time, we'll store the map in a variable and then display it:

scGOPmap <- leaflet(scmap) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addPolygons(stroke=TRUE,
              weight=1,
              smoothFactor = 0.2,
              fillOpacity = .75,
              popup=scpopup, 
              color= ~winnerPalette(scmap@data$winner),
              group="Winners"
  ) %>% 
    addLegend(position="bottomleft", colors=c("#984ea3", "#e41a1c"), labels=c("Trump", "Rubio"))  %>%

  addPolygons(stroke=TRUE,
     weight=1,
     smoothFactor = 0.2, 
     fillOpacity = .75, 
     popup=scpopup, 
     color= ~trumpPalette(scmap@data$`Donald J TrumpPct`),
     group="Trump"
    ) %>%

  addPolygons(stroke=TRUE,
              weight=1,
              smoothFactor = 0.2, 
              fillOpacity = .75, 
              popup=scpopup, 
              color= ~rubioPalette(scmap@data$`Marco RubioPct`),
              group="Rubio"
  ) %>%

  addPolygons(stroke=TRUE,
              weight=1,
              smoothFactor = 0.2, 
              fillOpacity = .75, 
              popup=scpopup, 
              color= ~cruzPalette(scmap@data$`Ted CruzPct`),
              group="Cruz"
  ) %>%

  addPolygons(stroke=TRUE,
              weight=1,
              smoothFactor = 0.2, 
              fillOpacity = .75, 
              popup=scpopup, 
              color= ~edPalette(scmap@data$PctCollegeDegree),
              group="College degs"
  ) %>%

  addLayersControl(
      baseGroups=c("Winners", "Trump", "Rubio", "Cruz", "College degs"),
      position = "bottomleft",
      options = layersControlOptions(collapsed = FALSE)
      ) 

And now display the map with:

scGOPmap

Interactive map with multiple layers. Click on the radio buttons at the bottom left to change which layer displays.

addLayersControl can have two types of groups: baseGroups, like used above, which allow only one layer to be viewed at a time; and overlayGroups, where multiple layers can be viewed at once and each turned off individually.

Step 10: Save your interactive map

If you're familiar with RMarkdown or Shiny, a Leaflet map can be embedded in an RMarkdown document or Shiny Web application. If you'd like to use this map as an HTML page on a website or elsewhere, save a Leaflet map with the htmlwidget package's saveWidget() function:

# install.packages("htmlwidgets")
library("htmlwidgets")
saveWidget(widget=scGOPmap, file="scGOPprimary.html")

You can also save the map with external resources such as jQuery and the Leaflet JavaScript code in a separate directory by using the selfcontained=FALSE argument and choosing the subdirectory for the dependency files:

# install.packages("htmlwidgets")
save(widget=scGOPmap2, file="scGOPprimary_withdependencies.html", selfcontained=FALSE, libdir = "js")

This should get you started on creating your own choropleth maps with R. To see how to create maps with latitude/longitude point markers, see Useful new R packages for data visualization and analysis.

Next: Learn R for beginners with our PDF

Join the newsletter!

Or

Sign up to gain exclusive access to email subscriptions, event invitations, competitions, giveaways, and much more.

Membership is free, and your security and privacy remain protected. View our privacy policy before signing up.

Error: Please check your email address.

More about ClickExcelGitHubGoogleInteractiveMicrosoft

Show Comments
[]