I modified Mike Bostock's Bilevel Partition so that only one level is viewable at a time and added labels.
This visualization also accepts negative values in the data, and displays them in Red color. The positive values are displayed in Green color
Click on any arc to zoom in. Click in the center to zoom out.
Last active
December 26, 2017 04:22
-
-
Save apoorvnandan/8eb44a1990d4d9250700 to your computer and use it in GitHub Desktop.
Zoomable Unilevel Partition
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> | |
<meta charset="utf-8"> | |
<head> | |
<title> Zoomable Unilevel Partition </title> | |
<style> | |
#SD { | |
color: white; | |
font-family: sans-serif; | |
z-index:100; | |
position:absolute; | |
top:350px; | |
left:480px; | |
} | |
</style> | |
</head> | |
<div id = "SD"></div> | |
<div id="body"></div> | |
<script src="http://apoorvnandan.github.io/unilevelpartition/jquery.js"></script> | |
<script src="http://apoorvnandan.github.io/unilevelpartition/d3.js"></script> | |
<script type="text/javascript"> | |
//DATA FOR THE VISUALIZATION | |
var x=[ | |
["APAC", 1, "SEA", 1, "POD1", 0.15], | |
["APAC", 1, "IN", 1, "POD2", -0.5], | |
["NACE", 0.4, "GB", 1, "POD1", 0.15], | |
["NACE", 0.4, "DE", 1, "POD2", 0.25], | |
["NACE", 0.4, "DK", 1, "POD3", 0.2], | |
["NACE", 0.4, "FR", 1, "POD4", 0.5], | |
["SEEMEA", 0.3, "IL", 1, "POD1", -0.5], | |
["SEEMEA", 0.3, "IL", 1, "POD2", -1], | |
["SEEMEA", 0.3, "IL", 1, "POD3", 0.5], | |
]; | |
var obj = function(name,x) { | |
return {"name":name,"size":Math.abs(x),"sign":x,"children":[]}; | |
}; | |
var root = new obj(); | |
root.name = 'Total'; | |
var column = x[0].length; | |
var row = x.length; | |
var parent = root; | |
var temp; var c,r,flag; var temp1,temp2; | |
for(c=0;c<column-1;c+=2) { | |
temp = new obj(); | |
temp.name = x[0][c]; | |
temp.sign = x[0][c+1]; | |
temp.size = Math.abs(temp.sign); | |
parent.children.push(temp); | |
parent = parent.children[0]; | |
} | |
for(r=1;r<row;r++) { | |
parent = root; | |
for(c=0;c<column-1;c+=2) { | |
flag=0; | |
for(d=0;d<parent.children.length;d++) { | |
if(parent.children[d].name == x[r][c]) { | |
parent = parent.children[d]; | |
if(c==column-2) {parent.sign+=x[r][c+1]; parent.size += Math.abs(x[r][c+1]);} //line added | |
flag=1; | |
} | |
} | |
if(flag==0) { | |
temp = new obj(); | |
{ temp.name = x[r][c]; temp.sign=x[r][c+1]; temp.size = Math.abs(temp.sign);} | |
parent.children.push(temp); | |
parent=parent.children[parent.children.length-1]; | |
} | |
} | |
} | |
console.log(root); | |
root.size=0; | |
for(var i=0;i<root.children.length;i++) { | |
root.size+=root.children[i].size; | |
} | |
var currentPos = $("#SD").offset().left; | |
var myColor = d3.scale.linear() | |
.domain([-1,0,1]) | |
.range(["red","white","green"]); | |
var margin = {top: 350, right: 480, bottom: 350, left: 480}, | |
radius = Math.min(margin.top, margin.right, margin.bottom, margin.left) - 10; | |
var svg = d3.select("body").append("svg") | |
.attr("width", margin.left + margin.right) | |
.attr("height", margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
var partition = d3.layout.partition() | |
.sort(function(a, b) { return d3.ascending(a.name, b.name); }) | |
.size([2 * Math.PI, radius]); | |
var arc = d3.svg.arc() | |
.startAngle(function(d) { return d.x; }) | |
.endAngle(function(d) { return d.x + d.dx - .01 / (d.depth + .5); }) | |
.innerRadius(function(d) { return radius / 3 * d.depth; }) | |
.outerRadius(function(d) { return radius / 3 * (d.depth + 1) - 1; }); | |
f(); | |
var level=0; | |
function f() { | |
// Compute the initial layout on the entire tree to sum sizes. | |
// Also compute the full name and fill color for each node, | |
// and stash the children so they can be restored as we descend. | |
partition | |
.value(function(d) { return d.size; }) | |
.nodes(root) | |
.forEach(function(d) { | |
d._children = d.children; | |
d.sum = d.value; | |
d.key = key(d); | |
}); | |
// Now redefine the value function to use the previously-computed sum. | |
partition | |
.children(function(d, depth) { return depth < 1 ? d._children : null; }) | |
.value(function(d) { return d.size; }); | |
var center = svg.append("circle") | |
.attr("r", radius / 3) | |
.on("click", zoomOut); | |
center.append("title") | |
.text("zoom out"); | |
var path = svg.selectAll("g") | |
.data(partition.nodes(root).slice(1)) | |
.enter().append("path") | |
.attr("d", arc) | |
.style("fill", function(d) { return myColor(d.sign); }) | |
.each(function(d) { this._current = updateArc(d); }) | |
.on("click", zoomIn); | |
var g = svg.selectAll("g") | |
.data(partition.nodes(root).slice(1)) | |
.enter().append("g"); | |
var text = g.append("text") | |
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; }) | |
.attr("x", function(d) { return (d.y); }) | |
.attr("dx", "6") // margin | |
.attr("dy", ".35em") // vertical-align | |
.attr("font-family", "sans-serif") | |
.text(function(d) {return d.name; }); | |
function computeTextRotation(d) { | |
return ((d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180; | |
} | |
function zoomIn(p) {g.attr("opacity", 0); | |
if (p.depth > 1) p = p.parent; | |
zoom(p, p); | |
} | |
function zoomOut(p) {g.attr("opacity", 0); | |
if (!p.parent) return; | |
zoom(p.parent, p); | |
} | |
// Zoom to the specified new root. | |
function zoom(root, p) { | |
if (document.documentElement.__transition__) return; | |
// Rescale outside angles to match the new layout. | |
var enterArc, | |
exitArc, | |
outsideAngle = d3.scale.linear().domain([0, 2 * Math.PI]); | |
function insideArc(d) { | |
return p.key > d.key | |
? {depth: d.depth - 1, x: 0, dx: 0} : p.key < d.key | |
? {depth: d.depth - 1, x: 2 * Math.PI, dx: 0} | |
: {depth: 0, x: 0, dx: 2 * Math.PI}; | |
} | |
function outsideArc(d) { | |
return {depth: d.depth + 1, x: outsideAngle(d.x), dx: outsideAngle(d.x + d.dx) - outsideAngle(d.x)}; | |
} | |
center.datum(root); | |
// When zooming in, arcs enter from the outside and exit to the inside. | |
// Entering outside arcs start from the old layout. | |
if (root === p) { enterArc = outsideArc, exitArc = insideArc, outsideAngle.range([p.x, p.x + p.dx]); } | |
path = path.data(partition.nodes(root).slice(1), function(d) { return d.key; }); | |
g = g.data(partition.nodes(root).slice(1), function(d) { return d.key; }); | |
// When zooming out, arcs enter from the inside and exit to the outside. | |
// Exiting outside arcs transition to the new layout. | |
if (root !== p) enterArc = insideArc, exitArc = outsideArc, outsideAngle.range([p.x, p.x + p.dx]); | |
d3.transition().duration(d3.event.altKey ? 7500 : 750).each(function() { | |
path.exit().transition() | |
.style("fill-opacity", function(d) { return d.depth === 1 + (root === p) ? 1 : 0; }) | |
.attrTween("d", function(d) { return arcTween.call(this, exitArc(d)); }) | |
.remove(); | |
path.enter().append("path") | |
.style("fill-opacity", function(d) { return d.depth === 2 - (root === p) ? 1 : 0; }) | |
.style("fill", function(d) { return myColor(d.sign); }) | |
.on("click", zoomIn) | |
.each(function(d) { this._current = enterArc(d); }); | |
g.enter().append("text") | |
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; }) | |
.attr("x", function(d) { return (d.y); }) | |
.attr("dx", "6") // margin | |
.attr("dy", ".35em") // vertical-align | |
.attr("font-family", "sans-serif") | |
.text(function(d) { return d.name; }); | |
path.transition() | |
.style("fill-opacity", 1) | |
.attrTween("d", function(d) { return arcTween.call(this, updateArc(d)); }); | |
}); | |
} | |
} | |
function key(d) { | |
var k = [], p = d; | |
while (p.depth) k.push(p.name), p = p.parent; | |
return k.reverse().join("."); | |
} | |
function arcTween(b) { | |
var i = d3.interpolate(this._current, b); | |
this._current = i(0); | |
return function(t) { | |
return arc(i(t)); | |
}; | |
} | |
function updateArc(d) { | |
return {depth: d.depth, x: d.x, dx: d.dx}; | |
} | |
d3.select(self.frameElement).style("height", margin.top + margin.bottom + "px"); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello Mr. Apoorv N.,
I'm Marcos, from Brazil and I saw your profile on "freelancer.com".
I need a Recurrent Neural Network to predict the Brazilian stock market (BOVESPA).
Can you build a RNN with a reasonable percentage of accuracy?
Sincerely and awaiting your response,
Antonio Marcos