block by wboykinm 492182b66a0d1a3dd5513ff5b71c900c

Metro choropleth

Full Screen

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

index.html



<!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>

avg_commute_time.csv

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

build_atlas_w_metros.sh

#!/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