Skip to content

Instantly share code, notes, and snippets.

@wboykinm
Last active December 16, 2019 14:42
Show Gist options
  • Save wboykinm/f8857b6b4e90f70d633eec138da126e9 to your computer and use it in GitHub Desktop.
Save wboykinm/f8857b6b4e90f70d633eec138da126e9 to your computer and use it in GitHub Desktop.
Bivariate cartogram
license: mit

An adaptation of the NPR hexgrid that sets hexagon size in play as a thematic variable.

Still needs a legend, but:

  • Hex size = relative population
  • Hex color = approximate solar energy potential
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
<style>
body { background-color: #fff; }
</style>
<svg id="cartogram" width="800" height="500"></svg>
<script>
// The svg
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
// Map and projection
var projection = d3.geoMercator()
.scale(600) // This is the zoom
.translate([1500, 750]); // You have to play with these values to center your map
// Path generator
var path = d3.geoPath()
.projection(projection)
// Colors
var lowColor = '#ffffff'
var highColor = '#bc2a66'
// load in the data
d3.queue()
.defer(d3.json, "us_states_hexgrid.geojson")
.defer(d3.csv, "sn.csv")
.await(ready);
function ready(error, geo, sn) {
if (error) throw error;
// get min/max of everything
var getArray = function(data,name) {
var dataArray = [];
for (var d = 0; d < data.length; d++) {
dataArray.push(parseInt(data[d][name]))
}
return dataArray
}
var min1 = d3.min(getArray(sn,'population'))
var max1 = d3.max(getArray(sn,'population'))
var min2 = d3.min(getArray(sn,'avg_sn'))
var max2 = d3.max(getArray(sn,'avg_sn'))
// create color scale
var colorRamp = d3.scaleSqrt()
.domain([min2,max2])
.range([lowColor,highColor])
// Join geojson and CSV (gotta be a better way of doing this)
for (var i = 0; i < sn.length; i++) {
// Grab State Name
var dataState = sn[i].state;
// Grab grouped record count
var dataPop = sn[i].population;
var dataSn = sn[i].avg_sn
// Find the corresponding state inside the GeoJSON
for (var j = 0; j < geo.features.length; j++) {
var geoState = geo.features[j].properties.abbrv;
if (dataState == geoState) {
// Copy the data value into the JSON
geo.features[j].properties.population = parseInt(dataPop);
geo.features[j].properties.avg_sn = parseInt(dataSn);
// Stop looking through the JSON
break;
}
}
}
// Draw the scaled features
svg.append("g")
.selectAll("path")
.data(geo.features)
.enter()
.append("path")
.attr("fill", function(d) { return colorRamp(d.properties.avg_sn) || 'rgba(255,255,255,0.2)' })
.attr("d", path)
.attr("stroke", "rgba(100,100,100,0.9)")
// create resize scale (via http://bl.ocks.org/rveciana/5928736)
.attr("transform", function(d) {
scale_factor = Math.sqrt(d.properties.population/(max1-min1));
var centroid = path.centroid(d),
x = centroid[0],
y = centroid[1];
return "translate(" + x + "," + y + ")"
+ "scale(" + scale_factor + ")"
+ "translate(" + -x + "," + -y + ")";
});
// Draw the mesh
svg.append("g")
.selectAll("path")
.data(geo.features)
.enter()
.append("path")
.attr("fill", "none")
.attr("d", path)
//.attr("stroke", "rgba(50,50,50,0.2)")
// Add the labels
svg.append("g")
.selectAll("labels")
.data(geo.features)
.enter()
.append("text")
.attr("x", function(d){return path.centroid(d)[0]})
.attr("y", function(d){return path.centroid(d)[1]})
.text(function(d){ return d.properties.abbrv})
.attr("text-anchor", "middle")
.attr("alignment-baseline", "central")
.style("font-size", 11)
.style("fill", "rgba(25,25,25,0.6)")
.attr("transform","translate(0,-15)")
}
</script>
id state population avg_sn
2 AK 733375
1 AL 4830620 72
5 AR 2958208 65
4 AZ 6641928 89
6 CA 38421464 83
8 CO 5278906 84
9 CT 3593222 73
11 DC 647484 64
10 DE 926454 72
12 FL 19645772 79
13 GA 10006693 68
15 HI 1406299 87
19 IA 3093526 75
16 ID 1616547 77
17 IL 12873761 73
18 IN 6568645 76
20 KS 2892987 71
21 KY 4397353 76
22 LA 4625253 75
25 MA 6705586 69
24 MD 5930538 75
23 ME 1329100 71
26 MI 9900571 62
27 MN 5419171 72
29 MO 6045448 77
28 MS 2988081 73
30 MT 1014699 77
37 NC 9845333 70
38 ND 721640 73
31 NE 1869365 78
33 NH 1324201 71
34 NJ 8904413 72
35 NM 2084117 86
32 NV 2798636 91
36 NY 19673174 77
39 OH 11575977 77
40 OK 3849733 77
41 OR 3939233 75
42 PA 12779559 77
44 RI 1053661 78
45 SC 4777576 76
46 SD 843190 70
47 TN 6499615 70
48 TX 26538614 80
49 UT 2903379 79
51 VA 8256630 75
50 VT 626604 77
53 WA 6985464 71
55 WI 5742117 70
54 WV 1851420 79
56 WY 579679 76
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment