A stacked area chart visualization of how people spend their time, by hour of day. Inspired by New York Times: How Different Groups Spend Their Day.
Data from American Time Use Survey, Table A-3A. Percent of the population engaging in selected activities by time of day, 12 AM to 11 AM, average for the combined years 2011-15. The tables for AM and PM were combined into one. An additional column was added that describes the Subcategory Level, which is expressed as indentation in the original publication. Another column "Presentable" was also added. Values here were manually entered to hand-pick the Activities presented. The value (2)-
means "Estimate is approximately zero.".
Uses d3-area-label to position labels.
forked from curran's block: Persons of Concern StreamGraph by Origin
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://unpkg.com/d3@4.10.0"></script>
<script src="https://unpkg.com/d3-area-label@1.2.0"></script>
<title>Refugees Streamgraph</title>
<style>
body {
margin: 0px;
}
.area-label {
font-family: sans-serif;
fill-opacity: 0.7;
fill: white;
}
path:hover {
fill-opacity: 1;
fill:black;
}
path {
fill-opacity: 0.8;
stroke-width: 0.5;
}
text {
pointer-events: none;
}
.axis--major .tick text, .legend text, .tooltip text {
fill: #585858;
font-family: sans-serif;
font-size: 16pt;
}
.axis--minor .tick text {
display: none;
}
.axis--major .tick line{
stroke: #ddd;
stroke-width: 2px;
}
.axis--minor .tick line{
stroke: #eee;
}
.axis .domain {
display: none;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
var parseHour = d3.timeParse("%H:%M %p");
var hourFormatter = d3.timeFormat("%I:%M %p");
var formatHour = function (date) {
var hourStr = hourFormatter(date);
if(hourStr[0] === "0"){
return hourStr.substr(1);
}
return hourStr;
};
d3.csv('atus.csv', function (rawData) {
var hours = Object.keys(rawData[0]).filter(function (d) {
return d.indexOf(":00") !== -1;
});
var activities = rawData.filter(function (d) {
return d.Presentable === "1";
})
var keys = activities.map(function (d) { return d.Activity; });
var data = hours.map(function (hour){
var row = { date: parseHour(hour) };
activities.forEach(function (d) {
row[d.Activity] = +d[hour].replace("(2)-", "0");
});
return row;
});
console.log(data);
render(data, keys);
});
var margin = { top: 0, bottom: 30, left: 50, right: 10 };
var svg = d3.select('svg');
var width = +svg.attr('width');
var height = +svg.attr('height');
var g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
var xAxisG = g.append('g')
.attr('class', 'axis');
var xAxisMinorG = xAxisG.append('g')
.attr('class', 'axis axis--minor');
var xAxisMajorG = xAxisG.append('g')
.attr('class', 'axis axis--major');
var marksG = g.append('g');
var stack = d3.stack()
.offset(d3.stackOffsetExpand)
.order(d3.stackOrderInsideOut)
;
var xValue = function (d) { return d.date; };
var xScale = d3.scaleTime();
var yScale = d3.scaleLinear();
var colorScale = d3.scaleOrdinal()
.range(d3.schemeCategory10);
var xAxisMajor = d3.axisBottom().scale(xScale).tickFormat(formatHour);
var xAxisMinor = d3.axisBottom().scale(xScale).ticks(30);
var area = d3.area()
.x(d => xScale(xValue(d.data)))
.y0(d => yScale(d[0]))
.y1(d => yScale(d[1]))
.curve(d3.curveBasis);
// Render StreamGraph
function render(data, keys) {
stack.keys(keys);
var stacked = stack(data);
var innerWidth = width - margin.right - margin.left;
var innerHeight = height - margin.top - margin.bottom;
xScale
.domain(d3.extent(data, xValue))
.range([0, innerWidth]);
yScale
.domain([
d3.min(stacked, function (series) {
return d3.min(series, function (d) { return d[0]; });
}),
d3.max(stacked, function (series) {
return d3.max(series, function (d) { return d[1]; });
})
])
.range([innerHeight, 0]);
colorScale.domain(d3.range(keys.length));
var paths = marksG.selectAll('path').data(stacked);
var pathsEnter = paths
.enter().append('path');
pathsEnter.merge(paths)
.attr('fill', function (d) { return colorScale(d.index); })
.attr('stroke', function (d) { return colorScale(d.index); })
.attr('d', area);
paths.select('title')
.merge(pathsEnter.append('title'))
.text(function (d) { return d.key; })
var labels = marksG.selectAll('text').data(stacked)
labels
.enter().append('text')
.attr('class', 'area-label')
.merge(labels)
.text(function (d) { return d.key; })
.attr('transform', d3.areaLabel(area).interpolateResolution(1000));
xAxisMajor.tickSize(-innerHeight);
xAxisMinor.tickSize(-innerHeight);
xAxisG.attr('transform', `translate(0,${innerHeight})`);
xAxisMajorG.call(xAxisMajor);
xAxisMinorG.call(xAxisMinor);
}
</script>
</body>
</html>
https://unpkg.com/d3@4.10.0
https://unpkg.com/d3-area-label@1.2.0