A simple way to download Census data within R as well as shapefiles can be found here.
This guided example will pull demographic data to create a map of the distribution of Arabs in the state of Michigan by Public Use Microdata Area (PUMA).
To get started, you will need to obtain an API key from the US Census. To do this, go here. (This doesn’t take long).
First, install the following packages:
# install.packages(c("tigris","acs","stringr"))
library(tigris)
library(acs)
library(stringr)
library(leaflet)
library(htmlwidgets)
Second, we get the spatial data (tigris):
# grab the spatial data (tigris)
pumas <- pumas(state='MI',cb=TRUE)
Different spatial data is available using different commands like: blocks, counties, county_subdivisions, places, school_districts, states, tracts, zctas.
Third, we pull tabular data (acs). This is where you will need your API key.
api.key.install(key="YOUR_API_KEY")
# create a geographic set to grab tabular data (acs)
geo <- geo.make(state=c('MI'),
puma='*')
The ’*’ tells R to pull all available PUMAs. If we were interested in a subset of PUMAs, we can create a vector of the PUMA numbers of interest.
endyr=2015
sp=5
tabnum = "B04006"
ancestry <- acs.fetch(endyear=endyr,span=sp,geography=geo,
table.number=tabnum,col.names="pretty")
# use of col.names="pretty" abve gives the full column definitions
# if you want Census variable IDs use col.names="auto".
# The resulting 'ancestry' object is not a data.frame -
# it's a list to see what's available
names(attributes(ancestry))
attr(ancestry,"acs.colnames")
attr(ancestry,"geography")
attr(ancestry,"estimate")
# convert to a data.frame for merging
ancestry.df <- data.frame(ancestry@geography$NAME,
paste0(str_pad(ancestry@geography$state,2,"left",pad="0"),
str_pad(ancestry@geography$publicusemicrodataarea,5,"left",pad="0")),
ancestry@estimate[,c("B04006. People Reporting Ancestry: Total:",
"B04006. People Reporting Ancestry: Arab:",
"B04006. People Reporting Ancestry: Arab: Egyptian",
"B04006. People Reporting Ancestry: Arab: Iraqi",
"B04006. People Reporting Ancestry: Arab: Jordanian",
"B04006. People Reporting Ancestry: Arab: Lebanese",
"B04006. People Reporting Ancestry: Arab: Moroccan",
"B04006. People Reporting Ancestry: Arab: Palestinian",
"B04006. People Reporting Ancestry: Arab: Syrian",
"B04006. People Reporting Ancestry: Arab: Arab",
"B04006. People Reporting Ancestry: Arab: Other Arab",
"B04006. People Reporting Ancestry: Assyrian/Chaldean/Syriac")],
stringsAsFactors=FALSE)
# do some cleaning of the data frame and create variables of interest
names(ancestry.df) <- c("name","GEOID","total","arabtotal","egyptian","iraqi","jordanian",
"lebanese","moroccan","palestinian","syrian","arab","otharab",
"chaldean")
ancestry.df$man.arabtotal<-ancestry.df$egyptian+ancestry.df$iraqi+ancestry.df$jordanian+ancestry.df$lebanese+
ancestry.df$moroccan+ancestry.df$palestinian+ancestry.df$syrian+ancestry.df$arab+ancestry.df$otharab
ancestry.df$allarab<-ancestry.df$egyptian+ancestry.df$iraqi+ancestry.df$jordanian+ancestry.df$lebanese+
ancestry.df$moroccan+ancestry.df$palestinian+ancestry.df$syrian+ancestry.df$arab+ancestry.df$otharab+
ancestry.df$chaldean
ancestry.df$pct.allarab <- 100*(ancestry.df$allarab/ancestry.df$total)
The final step before mapping the data: merge the data with the geography file.
# do the merge
ancestry.merged <- geo_join(pumas,ancestry.df,"GEOID10","GEOID")
Here is where we make the map. First we’ll specify the pop-up, then well create the map object, and then we’ll finally print the map.
# make the map
popup <- paste0("GEOID: ", ancestry.merged$NAME10, "<br>", "Percent of Population Arab:", round(ancestry.merged$pct.allarab,2))
pal <- colorNumeric(
palette = "YlGnBu",
domain = ancestry.merged$pct.allarab
)
map3<-leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = ancestry.merged,
fillColor = ~pal(pct.allarab),
color = "#b2aeae", # you need to use hex colors
fillOpacity = 0.7,
weight = 1,
smoothFactor = 0.2,
popup = popup) %>%
addLegend(pal = pal,
values = ancestry.merged$pct.allarab,
position = "bottomright",
title = "Percent of Population<br>Arab",
labFormat = labelFormat(suffix = "%"))
map3
# don't forget to save
saveWidget(map3,file="map3.html",selfcontained = F)
# this will save the map in your directory and will allow
# you to open it in a web browser to peruse
And there you go!
LS0tCnRpdGxlOiAiUGxvdHRpbmcgQ2Vuc3VzIERhdGEgYnkgUFVNQSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKQSBzaW1wbGUgd2F5IHRvIGRvd25sb2FkIENlbnN1cyBkYXRhIHdpdGhpbiBSIGFzIHdlbGwgYXMgc2hhcGVmaWxlcyBjYW4gYmUgZm91bmQgW2hlcmVdKGh0dHA6Ly96ZXZyb3NzLmNvbS9ibG9nLzIwMTUvMTAvMTQvbWFuaXB1bGF0aW5nLWFuZC1tYXBwaW5nLXVzLWNlbnN1cy1kYXRhLWluLXItdXNpbmctdGhlLWFjcy10aWdyaXMtYW5kLWxlYWZsZXQtcGFja2FnZXMtMy8pLgoKVGhpcyBndWlkZWQgZXhhbXBsZSB3aWxsIHB1bGwgZGVtb2dyYXBoaWMgZGF0YSB0byBjcmVhdGUgYSBtYXAgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiBBcmFicyBpbiB0aGUgc3RhdGUgb2YgTWljaGlnYW4gYnkgUHVibGljIFVzZSBNaWNyb2RhdGEgQXJlYSAoUFVNQSkuCgpUbyBnZXQgc3RhcnRlZCwgeW91IHdpbGwgbmVlZCB0byBvYnRhaW4gYW4gQVBJIGtleSBmcm9tIHRoZSBVUyBDZW5zdXMuIFRvIGRvIHRoaXMsIGdvIFtoZXJlXShodHRwczovL2FwaS5jZW5zdXMuZ292L2RhdGEva2V5X3NpZ251cC5odG1sKS4gKFRoaXMgZG9lc24ndCB0YWtlIGxvbmcpLgoKRmlyc3QsIGluc3RhbGwgdGhlIGZvbGxvd2luZyBwYWNrYWdlczoKYGBge3J9CiMgaW5zdGFsbC5wYWNrYWdlcyhjKCJ0aWdyaXMiLCJhY3MiLCJzdHJpbmdyIikpCmxpYnJhcnkodGlncmlzKQpsaWJyYXJ5KGFjcykKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkoaHRtbHdpZGdldHMpCmBgYAoKU2Vjb25kLCB3ZSBnZXQgdGhlIHNwYXRpYWwgZGF0YSAodGlncmlzKToKYGBge3J9CiMgZ3JhYiB0aGUgc3BhdGlhbCBkYXRhICh0aWdyaXMpCnB1bWFzIDwtIHB1bWFzKHN0YXRlPSdNSScsY2I9VFJVRSkKYGBgCgpEaWZmZXJlbnQgc3BhdGlhbCBkYXRhIGlzIGF2YWlsYWJsZSB1c2luZyBkaWZmZXJlbnQgY29tbWFuZHMgbGlrZTogYmxvY2tzLCBjb3VudGllcywgY291bnR5X3N1YmRpdmlzaW9ucywgcGxhY2VzLCBzY2hvb2xfZGlzdHJpY3RzLCBzdGF0ZXMsIHRyYWN0cywgemN0YXMuCgpUaGlyZCwgd2UgcHVsbCB0YWJ1bGFyIGRhdGEgKGFjcykuIFRoaXMgaXMgd2hlcmUgeW91IHdpbGwgbmVlZCB5b3VyIEFQSSBrZXkuCmBgYHtyfQphcGkua2V5Lmluc3RhbGwoa2V5PSJZT1VSX0FQSV9LRVkiKQoKIyBjcmVhdGUgYSBnZW9ncmFwaGljIHNldCB0byBncmFiIHRhYnVsYXIgZGF0YSAoYWNzKQpnZW8gPC0gZ2VvLm1ha2Uoc3RhdGU9YygnTUknKSwKICAgICAgICAgICAgICAgIHB1bWE9JyonKQpgYGAKClRoZSAnKicgdGVsbHMgUiB0byBwdWxsIGFsbCBhdmFpbGFibGUgUFVNQXMuIElmIHdlIHdlcmUgaW50ZXJlc3RlZCBpbiBhIHN1YnNldCBvZiBQVU1Bcywgd2UgY2FuIGNyZWF0ZSBhIHZlY3RvciBvZiB0aGUgUFVNQSBudW1iZXJzIG9mIGludGVyZXN0LgpgYGB7cn0KZW5keXI9MjAxNQpzcD01CnRhYm51bSA9ICJCMDQwMDYiCmFuY2VzdHJ5IDwtIGFjcy5mZXRjaChlbmR5ZWFyPWVuZHlyLHNwYW49c3AsZ2VvZ3JhcGh5PWdlbywKICAgICAgICAgICAgICAgICAgICAgIHRhYmxlLm51bWJlcj10YWJudW0sY29sLm5hbWVzPSJwcmV0dHkiKQoKIyB1c2Ugb2YgY29sLm5hbWVzPSJwcmV0dHkiIGFidmUgZ2l2ZXMgdGhlIGZ1bGwgY29sdW1uIGRlZmluaXRpb25zCiMgaWYgeW91IHdhbnQgQ2Vuc3VzIHZhcmlhYmxlIElEcyB1c2UgY29sLm5hbWVzPSJhdXRvIi4KCiMgVGhlIHJlc3VsdGluZyAnYW5jZXN0cnknIG9iamVjdCBpcyBub3QgYSBkYXRhLmZyYW1lIC0KIyBpdCdzIGEgbGlzdCB0byBzZWUgd2hhdCdzIGF2YWlsYWJsZQpuYW1lcyhhdHRyaWJ1dGVzKGFuY2VzdHJ5KSkKYXR0cihhbmNlc3RyeSwiYWNzLmNvbG5hbWVzIikKYXR0cihhbmNlc3RyeSwiZ2VvZ3JhcGh5IikKYXR0cihhbmNlc3RyeSwiZXN0aW1hdGUiKQoKIyBjb252ZXJ0IHRvIGEgZGF0YS5mcmFtZSBmb3IgbWVyZ2luZwphbmNlc3RyeS5kZiA8LSBkYXRhLmZyYW1lKGFuY2VzdHJ5QGdlb2dyYXBoeSROQU1FLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMChzdHJfcGFkKGFuY2VzdHJ5QGdlb2dyYXBoeSRzdGF0ZSwyLCJsZWZ0IixwYWQ9IjAiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3BhZChhbmNlc3RyeUBnZW9ncmFwaHkkcHVibGljdXNlbWljcm9kYXRhYXJlYSw1LCJsZWZ0IixwYWQ9IjAiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5jZXN0cnlAZXN0aW1hdGVbLGMoIkIwNDAwNi4gUGVvcGxlIFJlcG9ydGluZyBBbmNlc3RyeTogVG90YWw6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQjA0MDA2LiBQZW9wbGUgUmVwb3J0aW5nIEFuY2VzdHJ5OiBBcmFiOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkIwNDAwNi4gUGVvcGxlIFJlcG9ydGluZyBBbmNlc3RyeTogQXJhYjogRWd5cHRpYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCMDQwMDYuIFBlb3BsZSBSZXBvcnRpbmcgQW5jZXN0cnk6IEFyYWI6IElyYXFpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQjA0MDA2LiBQZW9wbGUgUmVwb3J0aW5nIEFuY2VzdHJ5OiBBcmFiOiBKb3JkYW5pYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCMDQwMDYuIFBlb3BsZSBSZXBvcnRpbmcgQW5jZXN0cnk6IEFyYWI6IExlYmFuZXNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQjA0MDA2LiBQZW9wbGUgUmVwb3J0aW5nIEFuY2VzdHJ5OiBBcmFiOiBNb3JvY2NhbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkIwNDAwNi4gUGVvcGxlIFJlcG9ydGluZyBBbmNlc3RyeTogQXJhYjogUGFsZXN0aW5pYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCMDQwMDYuIFBlb3BsZSBSZXBvcnRpbmcgQW5jZXN0cnk6IEFyYWI6IFN5cmlhbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkIwNDAwNi4gUGVvcGxlIFJlcG9ydGluZyBBbmNlc3RyeTogQXJhYjogQXJhYiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkIwNDAwNi4gUGVvcGxlIFJlcG9ydGluZyBBbmNlc3RyeTogQXJhYjogT3RoZXIgQXJhYiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkIwNDAwNi4gUGVvcGxlIFJlcG9ydGluZyBBbmNlc3RyeTogQXNzeXJpYW4vQ2hhbGRlYW4vU3lyaWFjIildLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKIyBkbyBzb21lIGNsZWFuaW5nIG9mIHRoZSBkYXRhIGZyYW1lIGFuZCBjcmVhdGUgdmFyaWFibGVzIG9mIGludGVyZXN0Cm5hbWVzKGFuY2VzdHJ5LmRmKSA8LSBjKCJuYW1lIiwiR0VPSUQiLCJ0b3RhbCIsImFyYWJ0b3RhbCIsImVneXB0aWFuIiwiaXJhcWkiLCJqb3JkYW5pYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAibGViYW5lc2UiLCJtb3JvY2NhbiIsInBhbGVzdGluaWFuIiwic3lyaWFuIiwiYXJhYiIsIm90aGFyYWIiLAogICAgICAgICAgICAgICAgICAgICAgICAiY2hhbGRlYW4iKQphbmNlc3RyeS5kZiRtYW4uYXJhYnRvdGFsPC1hbmNlc3RyeS5kZiRlZ3lwdGlhbithbmNlc3RyeS5kZiRpcmFxaSthbmNlc3RyeS5kZiRqb3JkYW5pYW4rYW5jZXN0cnkuZGYkbGViYW5lc2UrCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuY2VzdHJ5LmRmJG1vcm9jY2FuK2FuY2VzdHJ5LmRmJHBhbGVzdGluaWFuK2FuY2VzdHJ5LmRmJHN5cmlhbithbmNlc3RyeS5kZiRhcmFiK2FuY2VzdHJ5LmRmJG90aGFyYWIKYW5jZXN0cnkuZGYkYWxsYXJhYjwtYW5jZXN0cnkuZGYkZWd5cHRpYW4rYW5jZXN0cnkuZGYkaXJhcWkrYW5jZXN0cnkuZGYkam9yZGFuaWFuK2FuY2VzdHJ5LmRmJGxlYmFuZXNlKwogICAgICAgICAgICAgICAgICAgICBhbmNlc3RyeS5kZiRtb3JvY2NhbithbmNlc3RyeS5kZiRwYWxlc3RpbmlhbithbmNlc3RyeS5kZiRzeXJpYW4rYW5jZXN0cnkuZGYkYXJhYithbmNlc3RyeS5kZiRvdGhhcmFiKwogICAgICAgICAgICAgICAgICAgICBhbmNlc3RyeS5kZiRjaGFsZGVhbgphbmNlc3RyeS5kZiRwY3QuYWxsYXJhYiA8LSAxMDAqKGFuY2VzdHJ5LmRmJGFsbGFyYWIvYW5jZXN0cnkuZGYkdG90YWwpCmBgYAoKVGhlIGZpbmFsIHN0ZXAgYmVmb3JlIG1hcHBpbmcgdGhlIGRhdGE6IG1lcmdlIHRoZSBkYXRhIHdpdGggdGhlIGdlb2dyYXBoeSBmaWxlLgpgYGB7cn0KIyBkbyB0aGUgbWVyZ2UKYW5jZXN0cnkubWVyZ2VkIDwtIGdlb19qb2luKHB1bWFzLGFuY2VzdHJ5LmRmLCJHRU9JRDEwIiwiR0VPSUQiKQpgYGAKCkhlcmUgaXMgd2hlcmUgd2UgbWFrZSB0aGUgbWFwLiBGaXJzdCB3ZSdsbCBzcGVjaWZ5IHRoZSBwb3AtdXAsIHRoZW4gd2VsbCBjcmVhdGUgdGhlIG1hcCBvYmplY3QsIGFuZCB0aGVuIHdlJ2xsIGZpbmFsbHkgcHJpbnQgdGhlIG1hcC4KYGBge3J9CiMgbWFrZSB0aGUgbWFwCnBvcHVwIDwtIHBhc3RlMCgiR0VPSUQ6ICIsIGFuY2VzdHJ5Lm1lcmdlZCROQU1FMTAsICI8YnI+IiwgIlBlcmNlbnQgb2YgUG9wdWxhdGlvbiBBcmFiOiIsIHJvdW5kKGFuY2VzdHJ5Lm1lcmdlZCRwY3QuYWxsYXJhYiwyKSkKcGFsIDwtIGNvbG9yTnVtZXJpYygKICBwYWxldHRlID0gIllsR25CdSIsCiAgZG9tYWluID0gYW5jZXN0cnkubWVyZ2VkJHBjdC5hbGxhcmFiCikKCm1hcDM8LWxlYWZsZXQoKSAlPiUKICBhZGRQcm92aWRlclRpbGVzKCJDYXJ0b0RCLlBvc2l0cm9uIikgJT4lCiAgYWRkUG9seWdvbnMoZGF0YSA9IGFuY2VzdHJ5Lm1lcmdlZCwgCiAgICAgICAgICAgICAgZmlsbENvbG9yID0gfnBhbChwY3QuYWxsYXJhYiksIAogICAgICAgICAgICAgIGNvbG9yID0gIiNiMmFlYWUiLCAjIHlvdSBuZWVkIHRvIHVzZSBoZXggY29sb3JzCiAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjcsIAogICAgICAgICAgICAgIHdlaWdodCA9IDEsIAogICAgICAgICAgICAgIHNtb290aEZhY3RvciA9IDAuMiwKICAgICAgICAgICAgICBwb3B1cCA9IHBvcHVwKSAlPiUKICBhZGRMZWdlbmQocGFsID0gcGFsLCAKICAgICAgICAgICAgdmFsdWVzID0gYW5jZXN0cnkubWVyZ2VkJHBjdC5hbGxhcmFiLCAKICAgICAgICAgICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiLCAKICAgICAgICAgICAgdGl0bGUgPSAiUGVyY2VudCBvZiBQb3B1bGF0aW9uPGJyPkFyYWIiLAogICAgICAgICAgICBsYWJGb3JtYXQgPSBsYWJlbEZvcm1hdChzdWZmaXggPSAiJSIpKSAKbWFwMwoKIyBkb24ndCBmb3JnZXQgdG8gc2F2ZQpzYXZlV2lkZ2V0KG1hcDMsZmlsZT0ibWFwMy5odG1sIixzZWxmY29udGFpbmVkID0gRikKIyB0aGlzIHdpbGwgc2F2ZSB0aGUgbWFwIGluIHlvdXIgZGlyZWN0b3J5IGFuZCB3aWxsIGFsbG93CiMgeW91IHRvIG9wZW4gaXQgaW4gYSB3ZWIgYnJvd3NlciB0byBwZXJ1c2UKYGBgCgpBbmQgdGhlcmUgeW91IGdvIQoK