block by guilhermesimoes a7fe807098e92f1aa7a98179a6c2e90e

Box and Whisker

Full Screen

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.

index.html

<!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>