Cycle Plots are a useful technique for analysing cyclical patterns. They allow us to see both the overall pattern across the entire cycle and the trend for each point in the cycle across the entire range of time.
Cycle plots were originally developed by Cleveland, Dunn and Terpenning in the 1970s, and were brought to my attention by Stephen Few's Now You See It.
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
font: 12px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #999;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.axis .title,
.x.axis text {
font-size: 16px;
}
.line, .mean {
fill: none;
stroke: black;
stroke-width: 1.5px;
}
.mean {
stroke-opacity: 0.5;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.js"></script>
<script>
var margin = { top: 20, right: 20, bottom: 30, left: 50 },
width = 800 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var data = [ { day: "Sunday", data: [] },
{ day: "Monday", data: [] },
{ day: "Tuesday", data: [] },
{ day: "Wednesday", data: [] },
{ day: "Thursday", data: [] },
{ day: "Friday", data: [] },
{ day: "Saturday", data: [] } ];
var parseDate = d3.time.format("%Y%m%d").parse;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width],.1)
.domain([0,1,2,3,4,5,6]);
var intraDayX = d3.scale.linear()
.range([0, x.rangeBand()]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(0)
.tickFormat(function (d) { return data[d].day; });
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSize(3, 0);
var line = d3.svg.line()
.x(function(d, i) { return intraDayX(i); })
.y(function(d) { return y(d.items_sold) });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("data.json", function(error, rawData) {
rawData.forEach(function(d) {
d.date = parseDate(d.date);
d.items_sold = +d.items_sold;
data[d.date.getDay()].data.push(d);
});
data.forEach(function(d) {
d.mean = d3.mean(d.data, function(d) { return d.items_sold; });
});
intraDayX.domain([ 0, d3.max(data, function(d) { return d.data.length; })]);
y.domain(d3.extent(rawData, function(d) { return d.items_sold; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "title")
.attr("y", -5)
.style("text-anchor", "middle")
.text("Items Sold");
var days = svg.selectAll(".day")
.data(data)
.enter()
.append("g")
.attr("class", "day")
.attr("transform", function(d, i) { return "translate(" + x(i) + ",0)"; });
days.append("line")
.attr("class", "mean")
.attr("x1", 0)
.attr("y1", function(d) { return y(d.mean); })
.attr("x2", x.rangeBand())
.attr("y2", function(d) { return y(d.mean); });
days.append("path")
.datum( function(d) { return d.data; })
.attr("class", "line")
.attr("d", line);
});
</script>
</body>
Modified http://d3js.org/d3.v3.js to a secure url
https://d3js.org/d3.v3.js