Skip to content

Instantly share code, notes, and snippets.

@wboykinm
Last active March 21, 2018 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wboykinm/492182b66a0d1a3dd5513ff5b71c900c to your computer and use it in GitHub Desktop.
Save wboykinm/492182b66a0d1a3dd5513ff5b71c900c to your computer and use it in GitHub Desktop.
Metro choropleth
license: mit
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

A choropleth example showing commute time by U.S. metro area. This uses a variation on Mike Bostock's us-atlas that includes quantized metro areas as a separate object, and the build script is included here.

Built with blockbuilder.org

id avg_commute_time
46700 33.2718014397961
26900 26.9399681442023
29620 23.5285289256198
22660 24.9013125796755
40060 27.3101728768796
19260 25.2676349627779
42680 24.5370279751608
15540 24.6287472261448
35840 25.8617162354532
31540 23.8740217530605
21780 22.7333159395442
48300 20.0208795167369
16700 27.6299705782819
38900 28.2254463916226
28100 26.029916079569
27900 21.5476472726698
13020 22.8781204600149
37700 27.6079872839261
29700 23.8501593489083
27500 24.713449022116
34940 24.8583290135691
37620 22.9539947662585
22900 23.0321579805817
13820 28.7709873381413
44220 24.1566676240518
36500 27.2065038842361
47020 22.2575717577038
28140 25.0788649237822
39340 23.7682604991376
12940 29.3439759345537
22540 22.245538678912
29460 28.3890157314638
19500 20.3281539308412
14540 22.5968149250225
31460 27.7813319723208
31020 26.4510997096607
25620 24.7389814159201
10380 27.5137276947628
17660 22.823340746188
42060 21.2133911762298
15980 29.1319703130776
41620 24.9396999078215
46340 24.6681278875937
37100 28.313289664391
21500 21.0386244543656
47940 18.4802371376251
25500 21.6377717210663
16860 25.2114760717254
41980 34.2014887896454
39660 19.983309978696
39380 22.8897555861551
49340 30.703425921623
16740 28.318114555677
11340 25.2456879457897
41900 27.7283186194224
40220 24.8502226226383
40340 20.6643220097937
41060 22.9993327733863
32900 28.0986269174542
11700 23.4042556042395
36140 25.0980052258179
27340 27.7756452591145
30460 23.552445078158
44700 31.6604661112312
12020 24.2957466516122
40380 23.1849726391368
26980 20.534631533093
37980 32.0761669605558
32780 20.7966338375605
28660 23.0778487548775
10180 18.7920657320118
46140 23.3347064426795
31080 32.3676171537491
41780 22.7961715759044
30980 24.4325982113593
19060 24.1912996828502
45780 22.6165264277061
28700 24.7084770188893
16980 34.609720710865
45820 22.1517281211053
30780 24.9870115005364
40420 24.7004247625416
13900 20.2508665619311
25420 24.5680433029496
22520 25.8289460353911
29100 20.4723906903422
47580 22.9056675929939
41420 25.0535874006564
45060 22.9813614246616
29180 25.438471349615
24140 24.0956364197055
19180 22.1152877383243
39460 25.86084344888
39100 34.1006677499674
13380 22.4075919653935
44060 23.2793467769285
41500 24.3535909070077
36980 21.5703504471379
37460 23.7649447494725
36780 20.7526618620926
27140 25.9299149625193
48540 24.3423267528561
45940 29.6527053173796
24580 21.8872188433042
49700 30.3421501226982
31700 29.6688828579788
37340 26.0490739156098
11500 26.5305981652958
38660 25.8057855516456
29740 22.9550804254592
14740 32.1436541746859
12260 25.6821662079444
31740 18.9466181160455
19380 23.770565296653
45460 23.6787769097294
22140 23.577033363041
15940 24.217136658114
36420 24.1793607429766
31860 18.7247940879643
33660 26.4745335765994
31180 18.6950977958572
33140 24.7200454218
28740 29.1458136198529
34740 23.2990425310484
34620 22.8279137696446
15380 23.3042789070381
14500 24.9702679167185
14260 23.7194074473938
46060 27.069980348501
36260 24.5716336143808
19740 29.6776399843679
41100 19.6504096037921
36540 22.301029634443
30860 19.6980046737372
11100 20.7427696803887
13780 22.0510556151044
41860 34.6512443610634
35660 21.9001006136666
31340 25.5611936949571
25260 23.545584916013
34820 23.3716911792392
10900 29.8879009762901
17020 22.1119146093971
38300 28.924728217907
28020 23.0192453159548
40660 24.060108113923
21340 25.2429364529498
16820 26.5064558227356
33540 19.337404463855
27740 23.4315162589246
38540 19.5789015243165
33100 30.8200790697832
43300 27.1285937444104
35620 39.1241928310679
24860 24.7227076905373
43780 23.4646396953994
14020 24.1885883108945
43100 19.9762590702067
17860 20.816502319961
26180 31.1352792445996
34580 26.9338009017391
33700 28.4472089062605
33260 21.4089189420526
13980 22.5674872148713
39300 27.5279776633553
22380 20.4770403127098
20740 21.2111319720802
22500 24.7305495942179
13740 20.9775503279801
38340 21.8684223617316
19100 30.1648387690773
25540 25.8538232184213
43620 20.29300746857
19140 24.2967358211347
46220 25.3050404141313
46540 22.4715697223221
29020 23.393175764785
19780 22.1083180545088
45500 19.9378788010539
18580 22.4768796045248
40900 28.203106422355
24780 22.356912772439
10780 24.0700668561592
21940 29.9614282986443
17820 25.0491055926226
24500 17.4737258333193
22220 23.6680480788402
11300 27.4247493021813
17300 25.7925959990802
16300 21.6056468661913
49020 31.2537188949569
35980 25.1912299096563
33460 27.5454368659403
15500 25.9089881869543
17140 26.861236550772
41660 19.1489084650573
26820 21.8816516522973
42340 25.9342160467051
26420 32.1434961743009
25060 25.8479514023523
24540 27.9481540695303
37380 28.3392614548598
19820 28.8809919450884
12620 24.3268728633341
29940 22.9835832616581
25020 26.9484968401158
49620 29.37869135385
34900 26.0343013445959
49660 23.3652434821392
12700 25.5324808847435
47260 26.6146438842035
30140 25.2528699223401
29140 21.0391590033674
23540 23.747972605718
47300 24.9905466405124
26580 24.3933501187479
36100 27.557577847362
27060 21.0199990683664
20940 22.8610278237897
28940 25.1265802594468
13460 20.8553871525051
27780 24.7145931594879
11020 21.3128354203936
20500 25.7992076592935
12220 23.1619017503395
16940 17.0764930821108
44180 23.6831880028645
48660 17.9323454151787
38860 26.62374206062
28420 23.8249216578963
23580 29.2748183831844
21300 21.7044134045425
23420 24.1681844671172
48900 24.3226279525368
46660 22.1260044315118
45300 28.9584178096266
44940 24.5166188679245
32580 22.987649361862
10500 22.5244250876461
30020 19.5048048730867
17980 23.9035790899853
41700 27.7449739363076
33340 25.5189336643682
19660 27.4642572076869
13140 23.5790360994407
33780 26.3844371098515
17900 26.5461513226566
31900 23.37095752045
24300 22.479919171508
43340 23.994881795885
42020 23.1031082921673
10420 25.6036188922189
27180 21.9705380978418
42660 31.7967425368867
21820 20.2527058651455
30620 21.2982434056188
15260 23.7598919150557
31140 26.1816856081504
25860 25.0152957781757
39900 23.4351814496496
25980 24.4372300404069
36740 29.9691950777159
16580 20.8518576622172
12980 22.5222529746278
48700 21.6000397912132
12420 28.913069544796
27860 20.8438322952807
18700 21.4571632052047
44300 22.5416985103056
12540 25.8090726266249
33740 22.4513030834534
47220 25.7966016741015
29820 26.6112427663364
20020 24.8455928898792
16620 25.7757265960107
36220 23.161192695956
22020 19.0203382360259
42100 29.1759959747704
11460 26.050351012607
16180 20.0426733818825
11540 21.5636739224271
10580 24.9401248662525
40980 23.3563461157679
14860 31.9964223983724
42540 23.591013206918
39540 25.86190747509
39580 27.4629738436677
34060 25.8275831608702
32820 26.2038580891568
19460 27.5728667151045
30340 25.7188185265504
20100 28.550417394111
44600 27.1723253794301
25180 31.5430979807562
17780 21.1392973049245
43900 24.551386990227
41140 20.9784931968276
38060 28.6285276889508
18880 25.8063144745326
12060 33.7682568638979
42220 27.0974112230423
34100 27.6875038372593
41540 24.1565642618801
37860 25.7958723763118
21060 25.4057374486797
23060 22.911689845058
19340 21.4996647692607
49180 25.0049475157102
24660 24.3207053996275
37900 22.6232836456872
29340 22.609684140345
40140 33.7172137900511
26100 22.3321746676584
26380 26.6602817159269
18140 25.3426070090411
30700 20.5909622491463
22180 24.2287335882161
44140 24.9755892947573
23460 25.4898236092266
27620 22.451862158527
41940 29.3790100168093
33860 24.874224794473
47380 20.8546474225948
43580 19.5939830210894
47900 37.8591345856482
17460 26.9573299028757
48140 20.6294076462851
30300 17.9648277365896
39820 21.0615139814787
26620 24.2144183203994
16020 22.3503378826024
27100 24.7235256508825
26300 23.6547765429179
20220 18.7341130493883
49500 27.2128425910293
38940 28.4567557777652
41180 27.7807424242154
39740 26.6941458968696
12100 26.4351458248623
24220 17.2607549802341
29420 20.5575030097019
17420 25.1567685828365
16220 19.0526099817053
39140 24.409700446144
44100 21.2226380277055
11260 23.0036921130879
11180 19.9883290883082
48620 21.0759353023586
21660 21.8609755909578
14460 33.378108745361
35300 26.6654117281835
49740 20.298553014643
29540 24.8560370521887
27260 28.1585044959044
24340 24.7509626024838
10740 25.5292271065215
34980 29.2325345149675
41740 27.6915049061433
31420 24.8082188651227
24020 26.3766577983033
42140 23.7012384513423
40580 23.2532316283088
12580 33.2322477531467
21140 21.4075779326555
15180 21.7502643114738
14060 20.0149775072771
20260 22.1438813160762
45220 25.3148762486954
22420 27.7155973825783
35380 28.1396553552636
18020 21.7466532553036
49420 21.3907951031474
38220 23.9810753068784
#!/bin/bash
# mad requirements:
npm install topojson-client topojson-server topojson-simplify shapefile ndjson-cli d3-geo-projection mapshaper -g
rm -rvf us
mkdir -p build us
# get both metros and counties
if [ ! -f build/cb_2015_us_cbsa_5m.shp ]; then
curl -o build/cb_2015_us_cbsa_5m.zip 'https://www2.census.gov/geo/tiger/GENZ2015/shp/cb_2015_us_cbsa_5m.zip'
unzip -od build build/cb_2015_us_cbsa_5m.zip cb_2015_us_cbsa_5m.shp cb_2015_us_cbsa_5m.dbf
chmod a-x build/cb_2015_us_cbsa_5m.*
fi
if [ ! -f build/cb_2015_us_county_5m.shp ]; then
curl -o build/cb_2015_us_county_5m.zip 'https://www2.census.gov/geo/tiger/GENZ2015/shp/cb_2015_us_county_5m.zip'
unzip -od build build/cb_2015_us_county_5m.zip cb_2015_us_county_5m.shp cb_2015_us_county_5m.dbf
chmod a-x build/cb_2015_us_county_5m.*
fi
# awkwardly build them all
geo2topo -q 1e5 -n counties=<( \
shp2json -n build/cb_2015_us_county_5m.shp \
| ndjson-filter '!/000$/.test(d.properties.GEOID)' \
| ndjson-map '(d.id = d.properties.GEOID, delete d.properties, d)' \
| geoproject -n 'd3.geoAlbersUsa().scale(1280).translate([480, 300])') \
| toposimplify -f -p 0.25 \
| topomerge states=counties -k 'd.id.slice(0, 2)' \
| topomerge nation=states \
> us/10m.json
geo2topo -q 1e5 -n metros=<( \
shp2json -n build/cb_2015_us_cbsa_5m.shp \
| ndjson-filter '!/000$/.test(d.properties.GEOID)' \
| ndjson-map '(d.id = d.properties.GEOID, delete d.properties, d)' \
| geoproject -n 'd3.geoAlbersUsa().scale(1280).translate([480, 300])') \
| toposimplify -f -p 0.25 \
> us/10m-metros.json
mapshaper -i combine-files us/10m.json us/10m-metros.json -o us/10m-all.json
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #FEFFE1;
}
.states {
fill: none;
stroke: #333;
stroke-linejoin: round;
}
.tick { font: 9px sans-serif; }
</style>
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/topojson.v2.min.js"></script>
<script>
var palette = ['#ffffe0', '#ffcb91', '#fe8f6a', '#e65758', '#c0223b', '#8b0000'];
var stops = [10, 20, 25, 30, 35, 40];
var width = 1200,
height = 900;
var x = d3.scaleLinear()
.domain([stops[0],stops[stops.length - 1]])
.range([550,850]);
var color = d3.scaleThreshold()
.domain(stops)
.range(palette);
var path = d3.geoPath();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// Legend
var g = svg.append("g")
.attr("class", "key")
.attr("transform", "translate(0,40)");
g.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
if (d[0] == null) d[0] = x.domain()[0];
if (d[1] == null) d[1] = x.domain()[1];
return d;
}))
.enter().append("rect")
.attr("height", 8)
.attr("x", function(d) { return x(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
.attr("fill", function(d) { return color(d[0]); });
g.append("text")
.attr("class", "caption")
.attr("x", x.range()[0])
.attr("y", -6)
.attr("fill", "#000")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text("Average commute (minutes)");
g.call(d3.axisBottom()
.scale(x)
.tickSize(13)
.tickFormat(function(x, i) { return (i == 0 || i > 1) ? x : ''; })
.tickValues(color.domain())
)
.select(".domain")
.remove();
// End legend
d3.queue()
.defer(d3.json, "10m-all.json")
.defer(d3.csv, "avg_commute_time.csv")
.await(ready);
function ready(error, us, commute) {
if (error) throw error;
var commuteById = {};
commute.forEach(function(d) { commuteById[String(d.id)] = +d.avg_commute_time; });
svg.append("g")
.attr("class", "metros")
.selectAll("path")
.data(topojson.feature(us, us.objects.metros).features)
.enter().append("path")
.attr("d", path)
.attr("fill", function(d) { return color(commuteById[String(d.id)]) || 'rgba(0,0,0,0)'; });
svg.append("path")
.datum(topojson.feature(us, us.objects.states, function(a, b) { return a.id !== b.id; }))
.attr("class", "states")
.attr("d", path);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment