County-Level Choropleth in Plotly and R

October 19, 2017

(This article was first published on R – Modern Data, and kindly contributed to R-bloggers)

At Plotly, we are commonly asked about thematic maps — especially county-level choropleth maps. This style of map provides a visual illustration of variation across a geographic area. Some pertinent uses are population density, economic measurements, crime statistics, and election results. With Plotly, there are multiple ways to bring county-level choropleths to life. For example,

using ggplotly

or native plot_ly

or plot_mapbox

. . .

For now, we will look at how to create the US electoral map using the ggplotly method. For more information concerning the plot_ly and plot_mapbox examples, checkout our R documentation library.

 . . .

Before we get started, we have to retrieve the data. The 2016 US election data can be sourced from Kaggle. For the map data, county and state boundaries, we can us the Maps package via ggplot2, which is loaded with Plotly package. Thus, we can load the Plotly library and read in the election and map data. Additionally, we will make use of the dplyr package.



county_df <- map_data("county")
state_df <- map_data("state")

df <- read.csv("")

As we are using multiple datasets, we will need to ensure that county names match so that we are able to plot all the counties, parishes, etc.. Thus, we make sure county names are lower case and use gsub to remove any unnecessary words (such as “county” or “parish”) and characters. We do this to both datasets.

df <- subset(df, select = c(Clinton, Trump, county_name))

df$county_name %<>%
  gsub(" county", "", .) %>%
  gsub(" parish", "", .) %>%
  gsub(" ", "", .) %>%
  gsub("[.]", "", .)

county_df$subregion <- gsub(" ", "", county_df$subregion)

Next, we want to correct the vote measurement and then determine who won which county by checking which candidate had the greater amount of votes.

df$Clinton <- df$Clinton*100
df$Trump <- df$Trump*100

for (i in 1:length(df[,1])) {
  if (df$Clinton[i] > df$Trump[i]) {
    df$win[i] = 'Clinton'
  } else {
    df$win[i] = 'Trump'

Rename for consistency, then join the two datasets using dplyr and remove any duplicates.

names(df) <- c("clinton", "trump", "subregion", "win")

choropleth <- inner_join(county_df, df, by = "subregion")
choropleth <- choropleth[!duplicated(choropleth$order), ]

. . .

As previously illustrated, there are multiple ways to visualize county-level choropleths in Plotly but we will focus on using ggplot2 and converting it to a Plotly object with ggplotly. Here, call ggplot using longitude, latitude, and group, and geom_polygon to color counties by the winning candidate. Additionally, we utilize a third dataset (state boundaries) in the second geom_polygon to add a familiar shape to our map. Finally, remove the axes, grid lines, and background to set the theme.

p <- ggplot(choropleth, aes(long, lat, group = group)) +
  geom_polygon(aes(fill = win), 
               colour = alpha("white", 1/2), size = 0.1)  +
  geom_polygon(data = state_df, colour = "white", fill = NA) + 
  scale_fill_manual(values = c('blue','red')) +

. . .

Now using the magic of ggplotly, we can convert this static plot into an interactive Plotly object. Furthermore, we have the option of extending the Plotly object by adding layout attributes and, or, modifying existing, or default, attributes by utilizing the style function.

p <- ggplotly(p, tooltip = 'text') %>% 
    hovermode = 'x',
    margin = list(
      t = 20,
      b = 20,
      l = 20,
      r = 20),
    legend = list(
      orientation = 'h',
      x = 0.5,
      y = 1.01,
      xanchor = 'center'))

# use style to modify layer
p <- style(p, hoverinfo = 'none', traces = c(3))

# use plotly_build to modify layer
p <- plotly_build(p)
str(p$x$layout$annotations) # check annotations
p$x$layout$annotations = NULL # remove annotation

Once you’re happy with the final product, and have added your Plotly credentials, you can publish it to your Plotly account.

Sys.setenv("plotly_username" = " ... ")
Sys.setenv("plotly_api_key" = " ... ")

api_create(p, filename = 'US 2016 Election')

. . .

Want More?

If you like this, checkout the full code here and more examples via our R documentation library.

If you’re looking for something more in-depth, then consider attending the 2 day R/Shiny Master Class in NYC November 18–19, where you’ll cover topics such as extending ggplot2, animations, linked brushing, and Shiny, whilst learning to build “stats apps” that have rich and interactive controls.


To leave a comment for the author, please follow the link and comment on their blog: R – Modern Data. offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...

If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Search R-bloggers


Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)