Skip to content

Instantly share code, notes, and snippets.

@guilhermesimoes
Forked from HarryStevens/.block
Last active November 12, 2017 22:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guilhermesimoes/a7fe807098e92f1aa7a98179a6c2e90e to your computer and use it in GitHub Desktop.
Save guilhermesimoes/a7fe807098e92f1aa7a98179a6c2e90e to your computer and use it in GitHub Desktop.
Box and Whisker
license: gpl-3.0

An implementation of a box-and-whisker plot in D3.js. From Mike Bostock's similar block:

A box-and-whisker plot uses simple glyphs that summarize a quantitative distribution with five standard statistics: the smallest value, lower quartile, median, upper quartile, and largest value.

<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: "Helvetica Neue", sans-serif;
margin: 0;
}
.box, .line, .line-dotted {
stroke: #000;
stroke-width: 1.5px;
}
.box {
fill: #fff;
}
.line-dotted {
stroke-dasharray: 3,3;
}
.text {
font-size: .8em;
}
.text.three, .text.one {
text-anchor: end;
}
.label {
text-anchor: middle;
}
</style>
</head>
<body>
<div id="viz"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/d3-marcon/build/d3-marcon.min.js"></script>
<script src="https://unpkg.com/jeezy/lib/jeezy.min.js"></script>
<script>
var letters = "abcdefghij".split("");
var setup = d3.marcon().top(30).bottom(10).left(10).right(10).width(window.innerWidth).height(window.innerHeight);
setup.render();
var width = setup.innerWidth(),
height = setup.innerHeight(),
svg = setup.svg();
var x = d3.scaleBand().rangeRound([0, width]).padding(0.8).domain(letters);
var y = d3.scaleLinear().range([height, 0]);
var transitionDelay = function(d, i){ return i * 200; };
var dy = 6;
function generate_data(){
return letters.map(function(d){
return {
id: d,
max: jz.num.randBetween(900, 1000),
min: jz.num.randBetween(0, 100),
three: jz.num.randBetween(650, 850),
median: jz.num.randBetween(400, 600),
one: jz.num.randBetween(150, 350)
};
});
}
draw(generate_data());
d3.interval(function(){
draw(generate_data());
}, 2000);
function draw(data){
// update the y domain
y.domain([d3.min(data, function(d){ return d.min; }), d3.max(data, function(d){ return d.max; })]);
// JOIN
var group = svg.selectAll(".group")
.data(data, function(d, i){ return d.id; });
var new_group = group.enter()
.append("g")
.attr("class", "group");
// UPDATE
group.select(".box")
.transition().delay(transitionDelay)
.attr("y", function(d){ return y(d.three); })
.attr("height", function(d){ return y(d.one) - y(d.three); });
group.select(".line-dotted.top")
.transition().delay(transitionDelay)
.attr("y1", function(d){ return y(d.three); })
.attr("y2", function(d){ return y(d.max); });
group.select(".line-dotted.bottom")
.transition().delay(transitionDelay)
.attr("y1", function(d){ return y(d.one); })
.attr("y2", function(d){ return y(d.min); });
group.select(".line.top")
.transition().delay(transitionDelay)
.attr("y1", function(d){ return y(d.max); })
.attr("y2", function(d){ return y(d.max); });
group.select(".line.bottom")
.transition().delay(transitionDelay)
.attr("y1", function(d){ return y(d.median); })
.attr("y2", function(d){ return y(d.median); });
group.select(".line.med")
.transition().delay(transitionDelay)
.attr("y1", function(d){ return y(d.min); })
.attr("y2", function(d){ return y(d.min); });
group.select(".text.top")
.transition().delay(transitionDelay)
.attr("y", function(d){ return y(d.max); })
.text(function(d){ return d.max; });
group.select(".text.three")
.transition().delay(transitionDelay)
.attr("y", function(d){ return y(d.three); })
.text(function(d){ return d.three; });
group.select(".text.med")
.transition().delay(transitionDelay)
.attr("y", function(d){ return y(d.median); })
.text(function(d){ return d.median; });
group.select(".text.one")
.transition().delay(transitionDelay)
.attr("y", function(d){ return y(d.one); })
.text(function(d){ return d.one; });
group.select(".text.bottom")
.transition().delay(transitionDelay)
.attr("y", function(d){ return y(d.min); })
.text(function(d){ return d.min; });
// ENTER
new_group.append("rect")
.attr("class", "box")
.attr("x", function(d){ return x(d.id); })
.attr("y", function(d){ return y(d.three); })
.attr("width", x.bandwidth())
.attr("height", function(d){ return y(d.one) - y(d.three); });
new_group.append("line")
.attr("class", "line-dotted top")
.attr("x1", function(d){ return x(d.id) + x.bandwidth() / 2; })
.attr("x2", function(d){ return x(d.id) + x.bandwidth() / 2; })
.attr("y1", function(d){ return y(d.three); })
.attr("y2", function(d){ return y(d.max); });
new_group.append("line")
.attr("class", "line-dotted bottom")
.attr("x1", function(d){ return x(d.id) + x.bandwidth() / 2; })
.attr("x2", function(d){ return x(d.id) + x.bandwidth() / 2; })
.attr("y1", function(d){ return y(d.one); })
.attr("y2", function(d){ return y(d.min); });
new_group.append("line")
.attr("class", "line top")
.attr("x1", function(d){ return x(d.id); })
.attr("x2", function(d){ return x(d.id) + x.bandwidth(); })
.attr("y1", function(d){ return y(d.max); })
.attr("y2", function(d){ return y(d.max); });
new_group.append("line")
.attr("class", "line med")
.attr("x1", function(d){ return x(d.id); })
.attr("x2", function(d){ return x(d.id) + x.bandwidth(); })
.attr("y1", function(d){ return y(d.median); })
.attr("y2", function(d){ return y(d.median); });
new_group.append("line")
.attr("class", "line bottom")
.attr("x1", function(d){ return x(d.id); })
.attr("x2", function(d){ return x(d.id) + x.bandwidth(); })
.attr("y1", function(d){ return y(d.min); })
.attr("y2", function(d){ return y(d.min); });
new_group.append("text")
.attr("class", "text top")
.attr("x", function(d){ return x(d.id) + x.bandwidth() + dy; })
.attr("y", function(d){ return y(d.max); })
.attr("dy", dy)
.text(function(d){ return d.max; });
new_group.append("text")
.attr("class", "text three")
.attr("x", function(d){ return x(d.id) - dy; })
.attr("y", function(d){ return y(d.three); })
.attr("dy", dy)
.text(function(d){ return d.three; });
new_group.append("text")
.attr("class", "text med")
.attr("x", function(d){ return x(d.id) + x.bandwidth() + dy; })
.attr("y", function(d){ return y(d.median); })
.attr("dy", dy)
.text(function(d){ return d.median; });
new_group.append("text")
.attr("class", "text one")
.attr("x", function(d){ return x(d.id) - dy; })
.attr("y", function(d){ return y(d.one); })
.attr("dy", dy)
.text(function(d){ return d.one; });
new_group.append("text")
.attr("class", "text bottom")
.attr("x", function(d){ return x(d.id) + x.bandwidth() + dy; })
.attr("y", function(d){ return y(d.min); })
.attr("dy", dy)
.text(function(d){ return d.min; });
new_group.append("text")
.attr("class", "label")
.attr("x", function(d){ return x(d.id) + x.bandwidth() / 2; })
.attr("y", -10)
.text(function(d){ return d.id; });
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment