Last active
December 22, 2017 23:08
-
-
Save tezzutezzu/087047d6e9d8bf088cad86d6517e129a to your computer and use it in GitHub Desktop.
Incremental nested grouped chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<style> | |
.container { | |
fill:none; | |
stroke: black; | |
} | |
</style> | |
<svg width="960" height="500"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
var svg = d3.select("svg"), | |
margin = {top: 20, right: 20, bottom: 30, left: 40}, | |
width = +svg.attr("width") - margin.left - margin.right, | |
height = +svg.attr("height") - margin.top - margin.bottom, | |
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
var y = d3.scaleLinear() | |
.rangeRound([height, 0]); | |
let colors =["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]; | |
var z = d3.scaleOrdinal().range(colors); | |
function weightedRand(spec) { | |
var i, j, table=[]; | |
for(i=0; i<spec.length; i++) { | |
for (j=0; j<spec[i]*10; j++) { | |
table.push(i); | |
} | |
} | |
return function() { | |
return table[Math.floor(Math.random() * table.length)]; | |
} | |
} | |
let randFirst = weightedRand([.8, .4, .2]); | |
let randSecond = weightedRand([.9, .2, .01,.01]); | |
const ELEMENTS = 100; | |
const GROUPS = 4; | |
const PADDING = 1; | |
const INNERPADDING = .1; | |
let data = []; | |
d3.range(0,GROUPS).forEach(d=>{ | |
d3.range(0, ((Math.random()*4)|0)+1 ).forEach(dd=>{ | |
if(Math.random() > .6) { | |
d3.range(0, ELEMENTS).forEach(ddd=>{ | |
data.push({ | |
first: "f"+d, | |
second: "s"+dd, | |
third: Math.random() | |
}); | |
}); | |
} | |
}) | |
}); | |
let nestedData = d3.nest() | |
.key(d=>d.first).sortKeys(d3.descending) | |
.key(d=>d.second).sortKeys(d3.descending) | |
.key(d=>d.third) | |
.rollup(d=>d.length).entries(data) | |
nestedData.forEach(d=>{ | |
d.max = d3.max(d.values, dd=>dd.values.length) | |
d.sum = d3.sum(d.values, dd=>dd.values.length) | |
d.values.sort((a,b)=>b.values.length-a.values.length) | |
console.log(d.values) | |
}); | |
nestedData.sort((a,b)=>b.sum-a.sum); | |
let groupsNumber = d3.nest().key(d=>d.first + d.second).rollup(d=>d.length).entries(data).length; | |
let y0 = d3.scaleLinear().domain([0, groupsNumber + (PADDING * (nestedData.length-1)) + (INNERPADDING * (groupsNumber))]).range([0,height]).range([0, height]); | |
let x0 = d3.scaleLinear().domain([0, ELEMENTS]).range([0,width]).range([0, width]); | |
let yPositions = []; | |
let yPos = 0; | |
let gs = g.append("g") | |
.selectAll("g") | |
.data(nestedData) | |
.enter() | |
.append("g") | |
.attr("transform", (d,i)=>{ | |
let t = `translate(0, ${y0(yPos)})`; | |
yPos += d.values.length + PADDING + d.values.length * INNERPADDING; | |
return t; | |
}) | |
let gs2 = gs.selectAll(".bar") | |
.data(d=>d.values) | |
.enter() | |
.append("g") | |
.attr("transform", (d,i)=>{ | |
let t = `translate(0, ${y0(i + INNERPADDING)})`; | |
return t; | |
}) | |
gs2.selectAll(".bar") | |
.data((d,i)=>d.values.map(dd=>{ | |
return { | |
data: dd, | |
parent: d | |
} | |
})) | |
.enter() | |
.append("rect") | |
.attr("class", "bar") | |
.attr("fill", d=>z(d.parent.key)) | |
.attr("height", (d,i)=>y0(d.data.key -INNERPADDING)) | |
.attr("width", x0(1)) | |
.attr("x", (d,i)=>x0(i)) | |
.attr("y", (d,i)=>y0(1)-y0(d.data.key)) | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment