Skip to content

Instantly share code, notes, and snippets.

@godds
Last active September 30, 2019 10:52
Show Gist options
  • Save godds/6132680 to your computer and use it in GitHub Desktop.
Save godds/6132680 to your computer and use it in GitHub Desktop.
Cycle Plot
license: mit

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.

[
{ "date": "20130603", "items_sold": "41" },
{ "date": "20130604", "items_sold": "70" },
{ "date": "20130605", "items_sold": "84" },
{ "date": "20130606", "items_sold": "63" },
{ "date": "20130607", "items_sold": "63" },
{ "date": "20130608", "items_sold": "32" },
{ "date": "20130609", "items_sold": "34" },
{ "date": "20130610", "items_sold": "46" },
{ "date": "20130611", "items_sold": "68" },
{ "date": "20130612", "items_sold": "84" },
{ "date": "20130613", "items_sold": "61" },
{ "date": "20130614", "items_sold": "61" },
{ "date": "20130615", "items_sold": "34" },
{ "date": "20130616", "items_sold": "32" },
{ "date": "20130617", "items_sold": "48" },
{ "date": "20130618", "items_sold": "66" },
{ "date": "20130619", "items_sold": "86" },
{ "date": "20130620", "items_sold": "65" },
{ "date": "20130621", "items_sold": "65" },
{ "date": "20130622", "items_sold": "37" },
{ "date": "20130623", "items_sold": "35" },
{ "date": "20130624", "items_sold": "49" },
{ "date": "20130625", "items_sold": "65" },
{ "date": "20130626", "items_sold": "89" },
{ "date": "20130627", "items_sold": "60" },
{ "date": "20130628", "items_sold": "63" },
{ "date": "20130629", "items_sold": "39" },
{ "date": "20130630", "items_sold": "32" },
{ "date": "20130701", "items_sold": "54" },
{ "date": "20130702", "items_sold": "64" },
{ "date": "20130703", "items_sold": "92" },
{ "date": "20130704", "items_sold": "66" },
{ "date": "20130705", "items_sold": "59" },
{ "date": "20130706", "items_sold": "33" },
{ "date": "20130707", "items_sold": "34" },
{ "date": "20130708", "items_sold": "56" },
{ "date": "20130709", "items_sold": "63" },
{ "date": "20130710", "items_sold": "95" },
{ "date": "20130711", "items_sold": "60" },
{ "date": "20130712", "items_sold": "66" },
{ "date": "20130713", "items_sold": "34" },
{ "date": "20130714", "items_sold": "37" },
{ "date": "20130715", "items_sold": "62" },
{ "date": "20130716", "items_sold": "58" },
{ "date": "20130717", "items_sold": "104" },
{ "date": "20130718", "items_sold": "65" },
{ "date": "20130719", "items_sold": "65" },
{ "date": "20130720", "items_sold": "37" },
{ "date": "20130721", "items_sold": "33" },
{ "date": "20130722", "items_sold": "70" },
{ "date": "20130723", "items_sold": "57" },
{ "date": "20130724", "items_sold": "112" },
{ "date": "20130725", "items_sold": "64" },
{ "date": "20130726", "items_sold": "63" },
{ "date": "20130727", "items_sold": "34" },
{ "date": "20130728", "items_sold": "34" }
]
<!DOCTYPE html>
<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="http://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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment