This map shows unemployment data for census tracts in San Mateo county, California, from 2010.
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
xxxxxxxxxx
<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="https://d3js.org/colorbrewer.v1.min.js"></script>
<link href='https://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>
Modified http://d3js.org/colorbrewer.v1.min.js to a secure url
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js
https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.js
https://d3js.org/colorbrewer.v1.min.js