block by mbostock 3048740

Stacked Radial Area

Full Screen

This plot might be suitable for showing cyclical trends, though I’m not sure it’s a great idea as the radial display has a number of limitations:

Polar charts are pretty. But when in doubt, it’s probably best to stick to Cartesian coordinates.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.axis line {
  stroke: #000;
}

.axis path {
  fill: none;
  stroke: #000;
}

.axis + .axis g text {
  display: none;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var formatDate = d3.time.format("%a"),
    formatDay = function(d) { return formatDate(new Date(2007, 0, d)); };

var width = 960,
    height = 500,
    outerRadius = height / 2 - 10,
    innerRadius = 120;

var angle = d3.time.scale()
    .range([0, 2 * Math.PI]);

var radius = d3.scale.linear()
    .range([innerRadius, outerRadius]);

var z = d3.scale.category20c();

var stack = d3.layout.stack()
    .offset("zero")
    .values(function(d) { return d.values; })
    .x(function(d) { return d.time; })
    .y(function(d) { return d.value; });

var nest = d3.nest()
    .key(function(d) { return d.key; });

var line = d3.svg.line.radial()
    .interpolate("cardinal-closed")
    .angle(function(d) { return angle(d.time); })
    .radius(function(d) { return radius(d.y0 + d.y); });

var area = d3.svg.area.radial()
    .interpolate("cardinal-closed")
    .angle(function(d) { return angle(d.time); })
    .innerRadius(function(d) { return radius(d.y0); })
    .outerRadius(function(d) { return radius(d.y0 + d.y); });

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

d3.csv("data.csv", type, function(error, data) {
  if (error) throw error;

  var layers = stack(nest.entries(data));

  // Extend the domain slightly to match the range of [0, 2π].
  angle.domain([0, d3.max(data, function(d) { return d.time + 1; })]);
  radius.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]);

  svg.selectAll(".layer")
      .data(layers)
    .enter().append("path")
      .attr("class", "layer")
      .attr("d", function(d) { return area(d.values); })
      .style("fill", function(d, i) { return z(i); });

  svg.selectAll(".axis")
      .data(d3.range(angle.domain()[1]))
    .enter().append("g")
      .attr("class", "axis")
      .attr("transform", function(d) { return "rotate(" + angle(d) * 180 / Math.PI + ")"; })
    .call(d3.svg.axis()
      .scale(radius.copy().range([-innerRadius, -outerRadius]))
      .orient("left"))
    .append("text")
      .attr("y", -innerRadius + 6)
      .attr("dy", ".71em")
      .attr("text-anchor", "middle")
      .text(function(d) { return formatDay(d); });
});

function type(d) {
  d.time = +d.time;
  d.value = +d.value;
  return d;
}

</script>

data.csv

key,value,time
a,37,0
b,12,0
c,46,0
a,32,1
b,19,1
c,42,1
a,45,2
b,16,2
c,44,2
a,24,3
b,52,3
c,64,3
a,25,4
b,39,4
c,29,4
a,34,5
b,59,5
c,44,5
a,40,6
b,28,6
c,21,6