Skip to content

Instantly share code, notes, and snippets.

@MatteoTomassetti
Created February 24, 2016 19:18
Show Gist options
  • Save MatteoTomassetti/35f931d4dfcdac040b37 to your computer and use it in GitHub Desktop.
Save MatteoTomassetti/35f931d4dfcdac040b37 to your computer and use it in GitHub Desktop.
Unemployment in San Mateo County

This map shows unemployment data for census tracts in San Mateo county, California, from 2010.

  • Hover to get details for each census tract.
  • Pan and zoom by clicking, dragging, and scrolling.

The idea for doing this was inspired by the San Mateo Hackathon. The data comes from County of San Mateo Open Data Portal. Census tract shapes originally downloaded from US Census 2010 TIGER/Line® Shapefiles: Census Tracts then simplified using MapShaper.

Draws from the D3 Choropleth Example.

forked from curran's block: Unemployment in San Mateo County

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Example</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.js"></script>
<script src="http://d3js.org/colorbrewer.v1.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<style>
path {
stroke: gray;
stroke-width: 0.1px;
}
text {
font-family: 'Lato', sans-serif;
font-size: 1.5em;
/* This trick adds a heavy white shadow around the text. */
text-shadow:
0px 0px 6px white,
0px 0px 6px white,
0px 0px 6px white,
0px 0px 6px white,
0px 0px 6px white,
0px 0px 6px white,
0px 0px 6px white,
0px 0px 6px white,
0px 0px 6px white;
}
</style>
</head>
<body>
<script>
var width = 960;
var height = 500;
var csvFile = "Unemployment_Percentage_by_Census_Tract_San_Mateo_County_2010.csv";
var topoJSONFile = "tl_2010_06081_tract10.json";
// Use mercator so the map matches people's expectation,
// which has been learned from using Google Maps.
var projection = d3.geo.mercator()
.scale(65000)
.translate([width / 2, height / 2])
.center([-122.4, 37.54]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var choroplethG = svg.append("g");
var legendFormat = d3.format(".1%");
var legendSpacing = 40;
var legendLabelOffset = 35;
var legendBoxSize = 30;
var legendG = svg.append("g")
.attr("transform", "translate(50, 50)");
var tooltip = svg.append("text").attr("class", "tooltip");
var tooltipXOffset = 10;
var color = d3.scale.quantile()
.range(colorbrewer.Greys[9]);
var zoom = d3.behavior.zoom()
.scaleExtent([1, 20])
.on("zoom", function (){
choroplethG.attr("transform", "translate(" + d3.event.translate + ") scale(" + d3.event.scale + ")");
});
svg.call(zoom);
function showTooltip(data){
return function(d){
var value = data.get(d.properties.TRACTCE10);
tooltip
.attr("x", d3.event.pageX + tooltipXOffset)
.attr("y", d3.event.pageY)
.text(legendFormat(value) + " unemployment");
};
}
function hideTooltip(){
tooltip.text("");
}
fetchData(function (data){
fetchFeatures(function (features){
render(features, data);
});
});
function fetchData(callback){
// "data" will be a hash where keys are census tract codes
// and values are unemployment values.
var data = d3.map();
d3.csv(csvFile, function (d){
var id = d["Tract ID"];
var unemployment = parseFloat(d["Unemployment Rate"].replace("%","")) / 100;
data.set(id, unemployment);
}, function(){ callback(data); });
}
function fetchFeatures(callback){
d3.json(topoJSONFile, function(err, tracts){
// Parse the topoJSON structure.
var features = topojson.feature(tracts, tracts.objects.tl_2010_06081_tract10).features;
// Exclude the census tract in the water that has no unemployment data.
callback(features.filter(function (d){
return d.properties.TRACTCE10 !== "990100";
}));
});
}
function render(features, data){
color.domain(data.values());
renderChoropleth(features, data);
renderLegend(data);
}
function renderChoropleth(features, data){
choroplethG.selectAll("path")
.data(features)
.enter().append("path")
.attr("d", path)
.attr("fill", function (d){
return color(data.get(d.properties.TRACTCE10));
})
.on("mouseover", showTooltip(data))
.on("mousemove", showTooltip(data))
.on("mouseout", hideTooltip);
}
function renderLegend(data){
var extent = d3.extent(data.values());
var legendPoints = [extent[0]].concat(color.quantiles(), extent[1]);
var legendEntries = [];
legendPoints.forEach(function(d, i){
if(i < legendPoints.length - 1){
legendEntries.push([
legendPoints[i],
legendPoints[i + 1]
]);
}
});
var legend = legendG.selectAll("g.legendEntry")
.data(legendEntries)
.enter()
.append("g").attr("class", "legendEntry");
legend
.append("rect")
.attr("x", 0)
.attr("y", function(d, i) { return i * legendSpacing; })
.attr("width", legendBoxSize)
.attr("height", legendBoxSize)
.style("stroke", "gray")
.style("stroke-width", "1px")
.attr("fill", function(d){
return color(d[0]);
});
legend
.append("text")
.attr("x", legendLabelOffset)
.attr("y", function(d, i) { return i * legendSpacing; })
.attr("dy", "1em")
.text(function(d) {
var min = legendFormat(d[0]);
var max = legendFormat(d[1]);
return min + " - " + max;
});
}
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Tract ID Unemployment Rate
600100 9.7%
600200 14.3%
600300 3.4%
600401 6.2%
600402 8%
600500 11%
600600 10.2%
600700 8.9%
600800 10.9%
600900 9.2%
601000 9.2%
601100 9.1%
601200 5.8%
601300 13.1%
601400 8.8%
601501 8.1%
601502 9.8%
601601 6.2%
601603 3.6%
601604 2.3%
601605 5.3%
601700 12.6%
601800 4.2%
601901 5.3%
601902 0.6%
602000 4.7%
602100 10.7%
602200 3.3%
602300 5.9%
602400 8.1%
602500 6.7%
602600 6.7%
602700 5.9%
602800 5.4%
602900 9.1%
603000 7.1%
603100 4.7%
603200 9.5%
603300 5.4%
603400 5.4%
603700 6.4%
603801 5.9%
603802 6.3%
603900 5.7%
604000 1.2%
604101 9.3%
604102 3.3%
604200 14.7%
604400 8.3%
604500 3.9%
604600 7%
604700 4%
604800 4.6%
604900 4.6%
605000 5.3%
605100 4.8%
605200 4.4%
605300 5.8%
605400 9.1%
605500 6.5%
605600 7.5%
605700 3.8%
605800 2.5%
605900 11%
606000 0.6%
606100 2.6%
606200 9.5%
606300 2.6%
606400 2.2%
606500 1.5%
606600 4.6%
606700 4.2%
606800 5.1%
606900 3.6%
607000 5.7%
607100 3.9%
607200 7%
607300 2.2%
607400 3.9%
607500 3.7%
607600 6.1%
607701 8.6%
607702 6%
607800 3.4%
607900 5.9%
608001 5.4%
608002 1.5%
608004 3%
608013 9.7%
608023 11.3%
608100 5.8%
608200 5.1%
608300 5.4%
608400 6.4%
608501 8.1%
608502 5.7%
608600 9.3%
608700 4%
608800 5.4%
608900 5.7%
609000 5.4%
609100 6.6%
609201 6.8%
609202 6.7%
609300 6.1%
609400 4.3%
609500 6.8%
609601 4.6%
609602 2.3%
609603 3.8%
609700 4.3%
609800 4.4%
609900 4.1%
610000 3.3%
610100 6.5%
610201 6.4%
610202 2.6%
610203 6.6%
610302 1.3%
610303 7.5%
610304 7%
610400 15.7%
610500 9.7%
610601 9.8%
610602 10.6%
610700 5.3%
610800 3.4%
610900 8.2%
611000 5.5%
611100 5.5%
611200 5.8%
611300 3.5%
611400 3.7%
611500 9.6%
611600 3.9%
611700 8.4%
611800 7%
611900 11.3%
612000 12.1%
612100 5.8%
612500 6.8%
612600 4.1%
612700 2.9%
612800 4.6%
612900 5.6%
613000 4.5%
613200 4.7%
613300 8.7%
613400 1.9%
613501 4.7%
613502 5.9%
613600 0.9%
613700 8.4%
613800 2.1%
613900 8.3%
614000 4%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment