Transforming Bar Graph
by eprouver
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.1/underscore-min.js"></script>
<div>
<p>The yellow dots show the performance of the 'average' student.</p>
<p>'Work by Day' shows all of the exercises attempted in that day, and what the performance of an average student would be had they attempted those same exercises.</p>
<p>'Scores by Exercise' shows the breakdown per exercise with the corresponding average score.</p>
<p>I'll zoom this in to show only a selected day, and I'd like to color the dots to show if the student is above or below average.</p>
<p>Refresh to see new demo data</p>
</div>
<hr/>
<form>
<label>
<input type="radio" name="mode" value="grouped">Scores by Exercise</label>
<label>
<input type="radio" name="mode" value="stacked" checked="">Work By Day</label>
</form>
CSS
*{
font-family: Arial;
}
text{
font-size: 12px;
}
g.avg circle{
fill:yellow;
stroke: black;
stroke-width: 1px;
}
JavaScript
var days = d3.range(7);
var offsets = d3.range(7).map(function () {
return 0;
});
var stack = d3.layout.stack().out(function (d, y0, y) {
d.y0 = offsets[d.x];
offsets[d.x] += y
d.y = y;
});
var m = 7;
var maxTopics = 8;
days = _.map(days, function (v, i) {
return _.map(d3.range(maxTopics), function () {
var score = Math.random();
//Fake Data
return {
x: i, //Date
id: Math.random(),
y: score, //Score,
avg: Math.max(Math.sin(score) + (Math.random() * 0.5 - 0.25), 0)
}
}).sort(function (b, a) {
return b.y - a.y
})
});
//Sum of Averages for each day
var avgs = _.map(days, function (v) {
return _.reduce(v, function (i, v) {
return i + v.avg;
}, 0)
});
//Convert to Stack Layout
var layers = stack(days)
var yGroupMax = d3.max(layers, function (layer) {
return d3.max(layer, function (d) {
return d.y;
});
}),
yStackMax = d3.max(layers, function (layer) {
return d3.max(layer, function (d) {
return d.y0 + d.y;
});
});
var margin = {
top: 50,
right: 10,
bottom: 20,
left: 10
},
width = 860 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(d3.range(7))
.rangeRoundBands([0, width], 0.12);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var color = d3.scale.linear()
.domain([0, 1])
.range(["#ff0000", "#00ff00"]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(0)
.tickPadding(6)
.orient("bottom");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
var...