Last active
November 11, 2015 17:15
-
-
Save robroc/1802bf3311a941e82482 to your computer and use it in GitHub Desktop.
Stacked horizontal bar chart with D3
This file contains hidden or 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
drug | negative | neutral | positive | |
---|---|---|---|---|
Methamphetamine | 36 | 6 | 11 | |
MDMA | 26 | 9 | 16 | |
Cannabis | 13 | 13 | 11 | |
Peyote | 11 | 15 | 10 | |
PCP | 15 | 12 | 8 | |
Amphetamine | 23 | 5 | 6 | |
LSD | 13 | 12 | 9 | |
Ketamine | 12 | 12 | 6 | |
Mushrooms | 8 | 12 | 9 | |
Alcohol | 14 | 9 | 5 |
This file contains hidden or 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> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Horizontal stacked bar chart</title> | |
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> | |
<style type="text/css"> | |
body { | |
background-color: gray; | |
font-family: sans-serif; | |
} | |
#container { | |
width: 700px; | |
margin-left: auto; | |
margin-right: auto; | |
margin-top: 50px; | |
padding: 50px; | |
background-color: white; | |
box-shadow: 3px 3px 5px 6px #ccc; | |
} | |
h1 { | |
font-size: 24px; | |
margin: 0; | |
} | |
p { | |
font-size: 14px; | |
margin: 15px 0 50px 0; | |
} | |
svg { | |
background-color: white; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font-family: sans-serif; | |
font-size: 11px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container"> | |
<h1>The effects of drugs on your mind</h1> | |
<p>The drug information site Erowid.org lists all known effects of drugs, and categorizes them by negative, positive, and neutral effects. | |
These are the numbers of effects for selected drugs. <strong>Source:</strong> <a href="https://www.erowid.org/psychoactives/effects/effects.shtml">Erowid</a></p> | |
</div> | |
<script type="text/javascript"> | |
//Width and height | |
var w = 450; | |
var h = 280; | |
var margins = [30, 110, 40, 50]; | |
//Set up stack method | |
var stack = d3.layout.stack(); | |
var yScale = d3.scale.ordinal(); | |
var xScale = d3.scale.linear(); | |
//Colors correspond to index of stacked data | |
var colors = d3.scale.linear() | |
.domain([0, 1, 2]) | |
.range(["red", "gold", "green"]); | |
d3.csv("drugdata.csv", function(data) { | |
//console.log(data); | |
//Create a new array to hold restructured dataset | |
var dataset = [ | |
{ effect: "negative", | |
details: [] | |
}, | |
{ effect: "neutral", | |
details: [] | |
}, | |
{ effect: "positive", | |
details: [] | |
} | |
]; | |
//Loop once for each row in data | |
for (var i = 0; i < dataset.length; i++) { | |
for (var j = 0; j < data.length; j++) { | |
if (dataset[i].effect == "negative") { | |
dataset[i].details.push({ | |
drug: data[j].drug, | |
amount: data[j].negative | |
}); | |
} | |
else if (dataset[i].effect == "neutral") { | |
dataset[i].details.push({ | |
drug: data[j].drug, | |
amount: data[j].neutral | |
}); | |
} | |
else { | |
dataset[i].details.push({ | |
drug: data[j].drug, | |
amount: data[j].positive | |
}); | |
} | |
} | |
}; | |
//console.log(dataset); | |
// Create array with each color group for a color legend | |
series = dataset.map(function (d) { | |
return d.effect; | |
}); | |
dataset = dataset.map(function (d) { | |
return d.details.map(function (o, i) { | |
// Structure it so that your numeric | |
// axis (the stacked amount) is y | |
return { | |
y: +o.amount, | |
x: o.drug | |
}; | |
}); | |
}), | |
console.log(dataset); | |
//Data, stacked | |
stack(dataset); | |
var dataset = dataset.map(function (group) { | |
return group.map(function (d) { | |
// Invert the x and y values, and y0 becomes x0 | |
return { | |
x: +d.y, | |
y: d.x, | |
x0: +d.y0 | |
}; | |
}); | |
}); | |
//console.log(dataset); | |
//Set up scales | |
// Array of drug names for domain | |
var drugs = dataset[0].map(function (d) { | |
return d.y; | |
}); | |
yScale.domain(drugs) | |
.rangeRoundBands([0, h], 0.1); | |
xScale.domain([0, | |
d3.max(dataset, function(group) { | |
return d3.max(group, function(d) { | |
return d.x + d.x0 ; | |
}); | |
}) | |
]) | |
.range([0, w - margins[3]]); | |
//Create SVG element | |
var svg = d3.select("#container") | |
.append("svg") | |
.attr("width", w + margins[1] + margins [3] ) | |
.attr("height", h + margins[2]); | |
var xAxis = d3.svg.axis() | |
.scale(xScale) | |
.orient('bottom'); | |
var yAxis = d3.svg.axis() | |
.scale(yScale) | |
.orient('left'); | |
// Add a group for each row of data | |
var groups = svg.selectAll("g") | |
.data(dataset) | |
.enter() | |
.append("g") | |
.style("fill", function(d, i) { | |
return colors(i); | |
}); | |
// Add a rect for each data value | |
var rects = groups.selectAll("rect") | |
.data(function(d) { return d; }) | |
.enter() | |
.append("rect") | |
.attr("x", function(d) { | |
return xScale(d.x0) + margins[1]; | |
}) | |
.attr("width", function(d) { | |
return xScale(d.x); | |
}) | |
.attr("y", function(d, i) { | |
return yScale(d.y); | |
}) | |
.attr("height", function(d) { | |
return yScale.rangeBand() | |
}); | |
svg.append('g') | |
.attr('class', 'axis') | |
.attr('transform', 'translate(' + margins[1] + ',' + h + ')') | |
.call(xAxis); | |
svg.append('g') | |
.attr('class', 'axis') | |
.attr('transform', 'translate(' + margins[1] + ')') | |
.call(yAxis); | |
svg.append('rect') | |
.attr('fill', 'lightgrey') | |
.attr('width', 130) | |
.attr('height', 30 * dataset.length) | |
.attr('x', w - margins[3] + 10) | |
.attr('y', 100); | |
svg.append("text") | |
.attr('fill', 'black') | |
.attr('x', w/2) | |
.attr('y', h + 40 ) | |
.style("font-size", "12px") | |
.text("Number of effects"); | |
series.forEach(function (s, i) { | |
svg.append('text') | |
.attr('fill', 'black') | |
.attr('x', w - margins[2] + 40) | |
.attr('y', i * 24 + 122) | |
.text(s); | |
svg.append('rect') | |
.attr('fill', colors(i)) | |
.attr('width', 20) | |
.attr('height', 20) | |
.attr('x', w - margins[3] + 20 ) | |
.attr('y', i * 24 + 110); | |
}); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment