Skip to content

Instantly share code, notes, and snippets.

@rjl2168
Created April 26, 2018 11:44
Show Gist options
  • Save rjl2168/3df991db1f57b20139abeb07f8dce2c6 to your computer and use it in GitHub Desktop.
Save rjl2168/3df991db1f57b20139abeb07f8dce2c6 to your computer and use it in GitHub Desktop.
Mosaic Plot Example
license: mit
[
{
"Boro": "BRONX",
"Level": "FELONY",
"value": 0.0202540162933143
},
{
"Boro": "BRONX",
"Level": "MISDEMEANOR",
"value": 0.0517627506302758
},
{
"Boro": "BRONX",
"Level": "VIOLATION",
"value": 0.00898774680385934
},
{
"Boro": "BROOKLYN",
"Level": "FELONY",
"value": 0.0184796582425041
},
{
"Boro": "BROOKLYN",
"Level": "MISDEMEANOR",
"value": 0.035393061045235
},
{
"Boro": "BROOKLYN",
"Level": "VIOLATION",
"value": 0.00696610372499701
},
{
"Boro": "MANHATTAN",
"Level": "FELONY",
"value": 0.022936262865942
},
{
"Boro": "MANHATTAN",
"Level": "MISDEMEANOR",
"value": 0.0461997902732438
},
{
"Boro": "MANHATTAN",
"Level": "VIOLATION",
"value": 0.00760086085077431
},
{
"Boro": "QUEENS",
"Level": "FELONY",
"value": 0.0143868218451246
},
{
"Boro": "QUEENS",
"Level": "MISDEMEANOR",
"value": 0.0247547654974488
},
{
"Boro": "QUEENS",
"Level": "VIOLATION",
"value": 0.00544621875787301
},
{
"Boro": "STATEN ISLAND",
"Level": "FELONY",
"value": 0.01019776843812
},
{
"Boro": "STATEN ISLAND",
"Level": "MISDEMEANOR",
"value": 0.0316194824312504
},
{
"Boro": "STATEN ISLAND",
"Level": "VIOLATION",
"value": 0.00962387728543085
}
]
[
{
"Boro": "BRONX",
"Level": "FELONY",
"value": 0.0201941307394279
},
{
"Boro": "BRONX",
"Level": "MISDEMEANOR",
"value": 0.0410065122413651
},
{
"Boro": "BRONX",
"Level": "VIOLATION",
"value": 0.0100699310306927
},
{
"Boro": "BROOKLYN",
"Level": "FELONY",
"value": 0.016965139081926
},
{
"Boro": "BROOKLYN",
"Level": "MISDEMEANOR",
"value": 0.0278460864764008
},
{
"Boro": "BROOKLYN",
"Level": "VIOLATION",
"value": 0.00768044475753479
},
{
"Boro": "MANHATTAN",
"Level": "FELONY",
"value": 0.0212315374628742
},
{
"Boro": "MANHATTAN",
"Level": "MISDEMEANOR",
"value": 0.0394054025773027
},
{
"Boro": "MANHATTAN",
"Level": "VIOLATION",
"value": 0.00805969822367853
},
{
"Boro": "QUEENS",
"Level": "FELONY",
"value": 0.0132092956271051
},
{
"Boro": "QUEENS",
"Level": "MISDEMEANOR",
"value": 0.0206064668884646
},
{
"Boro": "QUEENS",
"Level": "VIOLATION",
"value": 0.00578554975581362
},
{
"Boro": "STATEN ISLAND",
"Level": "FELONY",
"value": 0.0106110101572429
},
{
"Boro": "STATEN ISLAND",
"Level": "MISDEMEANOR",
"value": 0.0252134911714967
},
{
"Boro": "STATEN ISLAND",
"Level": "VIOLATION",
"value": 0.00908584813503776
}
]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>NYC Crime Density per Capita by Borough</title>
<style>
body {
font: 10px sans-serif;
}
rect {
stroke: #000;
}
svg {
shape-rendering: crispEdges;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"> </script>
</head>
<body>
<h2> Please choose the year below to view the mosaic distribution of crime population density</h2>
<input id="2010" type="radio" name="stack" value="north">2010 <br>
<input id="2016" type="radio" name="stack" value="east" >2016 <br>
<em> Hover over the blocks to view the details </em>
<!--
<em> hober over the blocks to view the details </em>
<h2 id="2010">2010</h2> <div id="2016">2016</div> -->
<script type="text/javascript">
var width = 850,
height = 550,
margin = 70;
var x = d3.scaleLinear()
.range([0, width - 3 * margin]);
var y = d3.scaleLinear()
.range([0, height - 2 * margin]);
// var y = d3.scaleBand()
// .domain(["FELONY","MISDEMEANOR","VIOLATION")
// .range([0, height - 2 * margin]);
var z = d3.scaleOrdinal(d3.schemeCategory10);
console.log(z);
var n = d3.format(",d"),
p = d3.format("%");
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + 2 * margin + "," + margin + ")");
//var pathlnk= "mosaicdata.json";
var pathlnk="2010.json"
d3.select("[id='2016']").on("click", function () {
pathlnk="2016.json";
//alert("6");
d3.json(pathlnk, function(error, data) {
if (error) throw error;
var offset = 0;
d3.select("svg").remove();
var svg = d3.select("body").append("svg").attr("width","960").attr("height", "600"),
inner = svg.append("g").attr("transform", "translate(" + 2 * margin + "," + margin + ")");
// Nest values by Level. We assume each Level+Boro is unique.
var Levels = d3.nest()
.key(function(d) { return d.Level; })
.entries(data);
// Compute the total sum, the per-Level sum, and the per-Boro offset.
// You can use reduce rather than reduceRight to reverse the ordering.
// We also record a reference to the parent Level for each Boro.
var sum = Levels.reduce(function(v, p) {
return (p.offset = v) + (p.sum = p.values.reduceRight(function(v, d) {
d.parent = p;
return (d.offset = v) + d.value;
}, 0));
}, 0);
// Add x-axis ticks.
var xtick = svg.selectAll(".x")
//.data(x.ticks(10))
.enter().append("g")
.attr("class", "x")
.attr("transform", function(d) { return "translate(" + x(d) + "," + y(1) + ")"; });
xtick.append("line")
.attr("y2", 6)
.style("stroke", "#000");
xtick.append("text")
.attr("y", 8)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(p);
// Add y-axis ticks.
var ytick = svg.selectAll(".y")
//.data(y.ticks(10))
.enter().append("g")
.attr("class", "y")
.attr("transform", function(d) { return "translate(0," + y(1 - d) + ")"; });
ytick.append("line")
.attr("x1", -6)
.style("stroke", "#000");
ytick.append("text")
.attr("x", -8)
.attr("text-anchor", "end")
.attr("dy", ".35em")
.text(p);
// Add a group for each Level.
var Levels = svg.selectAll(".Level")
.data(Levels)
.enter().append("g")
.attr("class", "Level")
.attr("xlink:title", function(d) { return d.key; })
.attr("transform", function(d) { return "translate(" + x(d.offset / sum) + ")"; });
// Add a rect for each Boro.
var Boros = Levels.selectAll(".Boro")
.data(function(d) { return d.values; })
.enter().append("a")
.attr("class", "Boro")
.attr("xlink:title", function(d) { return d.Boro + " " + d.parent.key + ": " + n(d.value*100)+"%"; })
.append("rect")
.attr("y", function(d) { return y(d.offset / d.parent.sum); })
.attr("height", function(d) { return y(d.value / d.parent.sum); })
.attr("width", function(d) { return x(d.parent.sum / sum); })
.style("fill", function(d) { return z(d.Boro); });
//Boros.exit().remove();
});
});
d3.select("[id='2010']").on("click", function () {
pathlnk="2010.json";
alert(0);
d3.json(pathlnk, function(error, data) {
if (error) throw error;
var offset = 0;
d3.select("svg").remove();
var svg = d3.select("body").append("svg").attr("width","960").attr("height", "600"),
inner = svg.append("g");
// Nest values by Level. We assume each Level+Boro is unique.
var Levels = d3.nest()
.key(function(d) { return d.Level; })
.entries(data);
// Compute the total sum, the per-Level sum, and the per-Boro offset.
// You can use reduce rather than reduceRight to reverse the ordering.
// We also record a reference to the parent Level for each Boro.
var sum = Levels.reduce(function(v, p) {
return (p.offset = v) + (p.sum = p.values.reduceRight(function(v, d) {
d.parent = p;
return (d.offset = v) + d.value;
}, 0));
}, 0);
// Add x-axis ticks.
var xtick = svg.selectAll(".x")
//.data(x.ticks(10))
.enter().append("g")
.attr("class", "x")
.attr("transform", function(d) { return "translate(" + x(d) + "," + y(1) + ")"; });
xtick.append("line")
.attr("y2", 6)
.style("stroke", "#000");
xtick.append("text")
.attr("y", 8)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(p);
// Add y-axis ticks.
var ytick = svg.selectAll(".y")
// .data(y.ticks(10))
.enter().append("g")
.attr("class", "y")
.attr("transform", function(d) { return "translate(0," + y(1 - d) + ")"; });
ytick.append("line")
.attr("x1", -6)
.style("stroke", "#000");
ytick.append("text")
.attr("x", -8)
.attr("text-anchor", "end")
.attr("dy", ".35em")
.text(p);
// Add a group for each Level.
var Levels = svg.selectAll(".Level")
.data(Levels)
.enter().append("g")
.attr("class", "Level")
.attr("xlink:title", function(d) { return d.key; })
.attr("transform", function(d) { return "translate(" + x(d.offset / sum) + ")"; });
// Add a rect for each Boro.
var Boros = Levels.selectAll(".Boro")
.data(function(d) { return d.values; })
.enter().append("a")
.attr("class", "Boro")
.attr("xlink:title", function(d) { return d.Boro + " " + d.parent.key + ": " + n(d.value*100)+"%"; })
.append("rect")
.attr("y", function(d) { return y(d.offset / d.parent.sum); })
.attr("height", function(d) { return y(d.value / d.parent.sum); })
.attr("width", function(d) { return x(d.parent.sum / sum); })
.style("fill", function(d) { return z(d.Boro); });
//Boros.exit.remove();
});
});
</script>
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment