Skip to content

Instantly share code, notes, and snippets.

@robroc
Last active November 11, 2015 17:15
Show Gist options
  • Save robroc/1802bf3311a941e82482 to your computer and use it in GitHub Desktop.
Save robroc/1802bf3311a941e82482 to your computer and use it in GitHub Desktop.
Stacked horizontal bar chart with D3
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
<!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