A box-and-whisker plot with axes. Based on Mike Bostock's implementation. Instead of using individual svg elements as in Mike's implementation, here all boxplots are rendered with in one root element. This makes it easy to add axes.
Further differences between the two implementations are:
forked from jensgrubert's block: D3.js Boxplot with Axes and Labels
forked from sdalo2's block: D3.js Boxplot with Axes and Labels
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.box {
font: 10px sans-serif;
}
.box line,
.box rect,
.box circle {
fill: steelblue;
stroke: #000;
stroke-width: 1px;
}
.box .center {
stroke-dasharray: 3,3;
}
.box .outlier {
fill: none;
stroke: #000;
}
.axis {
font: 12px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="d3.v3.min.js"></script>
<script src="box.js"></script>
<script>
var labels = true; // show the text labels beside individual boxplots?
var margin = {top: 30, right: 50, bottom: 70, left: 50};
var width = 800 - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
var min = Infinity,
max = -Infinity;
// parse in the data
d3.csv("data2.csv", function(error, csv) {
var data = [];
var nested = d3.nest()
.key(d => d.series)
.entries(csv);
nested.forEach((series, i) => {
var item = [];
item[0] = series.key;
var values = series.values.map(d => +d.value);
item[1] = values.sort();
data.push(item);
});
min = d3.min(csv, d => +d.value);
max = d3.max(csv, d => +d.value);
var chart = d3.box()
.whiskers(iqr(1.5))
.height(height)
.domain([min, max])
.showLabels(labels);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("class", "box")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// the x-axis
var x = d3.scale.ordinal()
.domain( data.map(function(d) { console.log(d); return d[0] } ) )
.rangeRoundBands([0 , width], 0.7, 0.3);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
// the y-axis
var y = d3.scale.linear()
.domain([min, max])
.range([height + margin.top, 0 + margin.top]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
// draw the boxplots
svg.selectAll(".box")
.data(data)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + x(d[0]) + "," + margin.top + ")"; } )
.call(chart.width(x.rangeBand()));
// draw y axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text") // and text1
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style("font-size", "16px")
.text("Revenue in €");
// draw x axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height + margin.top + 10) + ")")
.call(xAxis)
.append("text") // text label for the x axis
.attr("x", (width / 2) )
.attr("y", 10 )
.attr("dy", ".71em")
.style("text-anchor", "middle")
.style("font-size", "16px")
.text("Quarter");
});
// Returns a function to compute the interquartile range.
function iqr(k) {
return function(d, i) {
console.log('d', d)
var q1 = d.quartiles[0],
q3 = d.quartiles[2],
iqr = (q3 - q1) * k,
i = -1,
j = d.length;
while (d[++i] < q1 - iqr);
while (d[--j] > q3 + iqr);
return [i, j];
};
}
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js