A visualization of a 7 Likert scale using d3v4. Based on the diverging stacked bar chart example from mbostock
forked from john-guerra's block: 7-Likert scale results visualization D3 v4
xxxxxxxxxx
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script>
var LIKERT_MAX = 7;
var LIKERT_NEUTRAL = Math.round(LIKERT_MAX/2);
var svg = d3.select("svg"),
margin = {top: 20, right: 30, bottom: 30, left: 60},
width = +svg.attr("width"),
height = +svg.attr("height");
var y = d3.scaleBand()
.padding(0.1)
.rangeRound([margin.top, height - margin.bottom]);
var x = d3.scaleLinear()
.rangeRound([margin.left, width - margin.right]);
var z = d3.scaleSequential(d3.interpolateRdBu)
.domain([-3,3]);
d3.csv("results.csv", function (err, data) {
if (err) throw err;
var series = d3.stack()
.keys(d3.range(1,LIKERT_MAX+1))
.offset(stackOffsetLikert)
(data);
y.domain(data.map(function(d) { return d.question; }));
x.domain([d3.min(series, stackMin), d3.max(series, stackMax)]);
svg.append("g")
.selectAll("g")
.data(series)
.enter().append("g")
.attr("fill", function(d) { return z(+d.key - LIKERT_NEUTRAL); })
.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("height", y.bandwidth)
.attr("y", function(d) { return y(d.data.question); })
.attr("x", function(d) { return x(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
svg.append("g")
.attr("transform", "translate(0," + (height-margin.bottom) + ")")
.call(d3.axisBottom(x));
svg.append("g")
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y));
function stackMin(serie) {
return d3.min(serie, function(d) { return d[0]; });
}
function stackMax(serie) {
return d3.max(serie, function(d) { return d[1]; });
}
// Assumes that the series include answers in the LIKERT_MAX Likert scale (default 7), therefore
// 1-3 are negative, 4 is neutral and 5-7 are positive
function stackOffsetLikert(series, order) {
if (!((n = series.length) > 1)) return;
for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) {
// Stack the neutral and positive values
for (yp = yn = 0, i = LIKERT_NEUTRAL-1; i < n; ++i) {
dy = (d = series[order[i]][j])[1] - d[0];
if (i=== (LIKERT_NEUTRAL-1)) {
//neutral goes centered in the middle
d[0] = yp -dy/2, d[1] = yp += dy/2;
} else {
d[0] = yp, d[1] = yp += dy;
}
}
// Now stack the negative values
for (yp = yn = 0, i = LIKERT_NEUTRAL-1; i >= 0 ; --i) {
dy = (d = series[order[i]][j])[1] - d[0];
if (i=== (LIKERT_NEUTRAL-1)) {
yp -= dy/2;
} else
if (i <(LIKERT_NEUTRAL-1)) {
d[1] = yp, d[0] = yp -= dy;
}
}
}
}
})
</script>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-color.v1.min.js
https://d3js.org/d3-interpolate.v1.min.js
https://d3js.org/d3-scale-chromatic.v1.min.js