From charlesreid1

MY goal in making this map of North Carolina was to gain more familiarity with the Census Reporter API, and start to dig down past the county level, to the zip code, area code, and census tract levels.

Starting Point

State and County Data

I started out with some code I wrote for my Census Map, which grabbed California county information, except this time I wrote a code that would turn state names and abbreviations into FIPS codes (here: http://www.census.gov/geo/reference/ansi_statetables.html), necessary to obtain geographic information from the Census Bureau or from Census Reporter, whose lovely API I was using.

STATE|STUSAB|STATE_NAME|STATENS
01|AL|Alabama|01779775
02|AK|Alaska|01785533
04|AZ|Arizona|01779777
05|AR|Arkansas|00068085
06|CA|California|01779778
08|CO|Colorado|01779779
09|CT|Connecticut|01779780
10|DE|Delaware|01779781
11|DC|District of Columbia|01702382
12|FL|Florida|00294478
13|GA|Georgia|01705317
15|HI|Hawaii|01779782
16|ID|Idaho|01779783
17|IL|Illinois|01779784
18|IN|Indiana|00448508
19|IA|Iowa|01779785
20|KS|Kansas|00481813
21|KY|Kentucky|01779786
22|LA|Louisiana|01629543
23|ME|Maine|01779787
24|MD|Maryland|01714934
25|MA|Massachusetts|00606926
26|MI|Michigan|01779789
27|MN|Minnesota|00662849
28|MS|Mississippi|01779790
29|MO|Missouri|01779791
30|MT|Montana|00767982
31|NE|Nebraska|01779792
32|NV|Nevada|01779793
33|NH|New Hampshire|01779794
34|NJ|New Jersey|01779795
35|NM|New Mexico|00897535
36|NY|New York|01779796
37|NC|North Carolina|01027616
38|ND|North Dakota|01779797
39|OH|Ohio|01085497
40|OK|Oklahoma|01102857
41|OR|Oregon|01155107
42|PA|Pennsylvania|01779798
44|RI|Rhode Island|01219835
45|SC|South Carolina|01779799
46|SD|South Dakota|01785534
47|TN|Tennessee|01325873
48|TX|Texas|01779801
49|UT|Utah|01455989
50|VT|Vermont|01779802
51|VA|Virginia|01779803
53|WA|Washington|01779804
54|WV|West Virginia|01779805
55|WI|Wisconsin|01779806
56|WY|Wyoming|01779807
60|AS|American Samoa|01802701
66|GU|Guam|01802705
69|MP|Northern Mariana Islands|01779809
72|PR|Puerto Rico|01779808
74|UM|U.S. Minor Outlying Islands|01878752
78|VI|U.S. Virgin Islands|01802710

Further Sub-Levels

Via the Census Bureau's own technical documentation, http://www.census.gov/prod/cen2010/doc/sf1.pdf (it is very extensive), we can obtain the following geographical entity hierarchy:

CensusDocumentationHierarchyWords.png

CensusDocumentationHierarchyChart.png

Next, I headed over to the Census Reporter API documentation: https://github.com/censusreporter/census-api/blob/master/API.md

This didn't say anything specific about geographies below the county level, so I assumed they were there, I just needed to request them correctly.

Sure enough, I grabbed the geoid for Dare County, NC, which was 05000US37055.

NCMap1.png

I then fed that geoid to the Census Reporter API, and it gave me information about the county:

$ curl "http://api.censusreporter.org/1.0/geo/tiger2013/05000US37055"
{"geometry": null, "type": "Feature", "properties": {"awater": 3054395108, "display_name": "Dare County, NC", "simple_name": "Dare County", "sumlevel": "050", "population": 34289, "full_geoid": "05000US37055", "aland": 992627006}}

and geometry information:

$ curl "http://api.censusreporter.org/1.0/geo/tiger2013/05000US37055?geom=True"
{"geometry": {"type": "MultiPolygon", "coordinates": [[[[-75.76384399999999, 35.233886], [-75.868684, 35.579451999999996], [-75.879179, 35.604172], [-75.87683299999999, 35.628116999999996], [-75.88395299999999, 35.632784], [-75.891953, 35.643328], [-75.890496, 35.652259], [-75.89834499999999, 35.661057], [-75.901164, 35.668997999999995], [-76.027445, 35.669094], [-76.03084299999999, 35.663227], [-76.035266, 35.662022], [-76.045987, 35.666117], [-76.029265, 35.682038999999996], [-76.022328, 35.709224999999996], [-76.025088, 35.721156], [-76.01927599999999, 35.752763], [-76.02239, 35.81066], [-76.01769399999999, 35.865356], [-76.00917799999999, 35.894453], [-75.987466, 35.916453], [-75.978991, 35.964459999999995], [-75.963734, 35.984291999999996], [-75.948736, 35.994425], [-75.78040899999999, 36.047422999999995], [-75.767448, 36.055639], [-75.763783, 36.062792], [-75.763192, 36.074594], [-75.77425, 36.103245], [-75.776439, 36.135726999999996], [-75.77865899999999, 36.142323999999995], [-75.789363, 36.154436], [-75.789075, 36.172205999999996], [-75.80169599999999, 36.187985], [-75.79943, 36.202217999999995], [-75.813189, 36.223544], [-75.70907799999999, 36.244983999999995], [-75.666246, 36.148924], [-75.566047, 35.975614], [-75.48050099999999, 35.814206999999996], [-75.46623699999999, 35.801314999999995], [-75.460815, 35.784524], [-75.437617, 35.74696], [-75.41781999999999, 35.686082], [-75.406815, 35.636972], [-75.40039, 35.593512], [-75.400849, 35.558718], [-75.402422, 35.54421], [-75.415089, 35.50018], [-75.426135, 35.386922999999996], [-75.447751, 35.309794], [-75.459334, 35.246552], [-75.468477, 35.21519], [-75.484571, 35.187577], [-75.505059, 35.174426], [-75.53217599999999, 35.167148999999995], [-75.55758399999999, 35.170535], [-75.581108, 35.183783999999996], [-75.59536899999999, 35.182826999999996], [-75.63621499999999, 35.172205], [-75.70737, 35.146111], [-75.73662, 35.140564999999995], [-75.76384399999999, 35.233886]]]]}, "type": "Feature", "properties": {"awater": 3054395108, "display_name": "Dare County, NC", "simple_name": "Dare County", "sumlevel": "050", "population": 34289, "full_geoid": "05000US37055", "aland": 992627006}}

Well, nothing contained in that JSON about sub-levels...

There is code for adding a tile layer to, e.g., a Leaflet map, using this URL:

http://api.censusreporter.org/1.0/geo/tiger2013/tiles/<sumlevel>/<zoom>/<x>/<y>.geojson

But this wouldn't accomplish the goal of getting GeoJSON data falling within a given county - it would get GeoJSON data for a map tile.

The solution is to request information about a particular level of geogrpahic entites, and pass it a geo_id to restrict the search. This can be done using the following API URL:

http://api.censusreporter.org/1.0/geo/show/tiger2013?geo_ids=<geo entity level>|<geo id>

So to find information about census tracts, which were level 140 (different levels and corresponding codes are listed on this page: [1]), for Dare County, North Carolina, which has geoid 05000US37055, we would request the URL:

http://api.censusreporter.org/1.0/geo/show/tiger2013?geo_ids=140|05000US37055

Downloading Census Tract Data for Counties

As mentioned, I used the following API URL to get census tract boundaries for Dare County, North Carolina:

$ curl http://api.censusreporter.org/1.0/geo/show/tiger2013?geo_ids=140|05000US37055

Using curl, from the command line, returns the JSON to stdout. We can capture it in a JSON file by saying:

$ curl http://api.censusreporter.org/1.0/geo/show/tiger2013?geo_ids=140|05000US37055 > dare_county_nc.json

Now we can drop that JSON file as a layer onto our Leaflet map, and voila! we have our census tracts:

NCCensusMap.png

Map Plan

My plan for the map is to use Python to loop over a list of particular counties, request all census tracts for those counties, and map them.

Overlay of Census Tracts

There are two ways to overlay census tracts.

Download GeoJson

The first way is to download the GeoJson to a file, and serve it yourself. In this case, your Javascript will look like this:

var geoj = new L.geoJson.ajax("dare_census_tracts.json",{onEachFeature:enhanceLayer}).addTo(map);

Grab GeoJson from URL

The other, more seamless option is to get the Json directly from the API of Census Reporter. You can do this with the following code (requires jQuery):

rooturl = "http://api.censusreporter.org/1.0/geo/show/tiger2013?geo_ids=140|05000US37055";

$.ajax({
    type: "GET",
    url: rooturl,
    success: function (data) {
        var geojson = new L.geoJson(data, {
            style: {
                fillColor: '#CFC',
                fillOpacity: 0.20,
                stroke: true,
                color: '#222',
                weight: 1
            },

            onEachFeature: function(feature, layer){
                popupText = "";
                popupText += feature.properties.name;
            }

        }).addTo(map2);

    }
});

Final Product

References and Links