block by renecnielsen b377db6afcc346d63929

Simple Difference Chart with d3.svg.area

Full Screen

A difference chart of presidential approval ratings of the Obama and Bush (43) administrations. Difference charts graphically encode the variance between two time series (typically) coloring the variance to indicate which time series has a higher value during that period. All the examples I’ve seen of difference charts in D3 use clipping or convoluted mechanisms to create the difference area.

Here’s an example that just uses d3.svg.area and defines the y value as the maximum of the two time series points at that position and the y0 value as whichever time series you’re using as the baseline. To give the chart the expected outlines, d3.svg.line is used to draw each time series on top of the difference areas.

This chart was used in my exploration of figure/ground and metastability in data visualization.

forked from emeeks‘s block: Simple Difference Chart with d3.svg.area

index.html

<!DOCTYPE html>

<head>
  <title>Difference Chart</title>
</head>
<meta charset="utf-8">
<style>

svg{
  background-color: #eee;
  margin-top: 20px;
}

path.domain {
  fill: none;
}

g.tick > line {
  stroke: white;
  stroke-width: 1px;
}

</style>
<body>
<div id="viz"></div>
</body>


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

var width = 500,
    height = 500;

xScale = d3.scale.linear().domain([0,10]).range([40,760]);
yScale = d3.scale.linear().domain([0,10]).range([60,830]);

svg = d3.select('#viz')
    .append('svg')
    .attr({width: width, height: height});

  svg.append("g").attr("class","linechart");

  linechart = d3.select("g.linechart");

d3.json("bush_obama.json", createLineChart);

function createLineChart(data) {

  data.forEach(function(d) {
    d.b_a = parseInt(d.b_a);
    d.o_a = parseInt(d.o_a);
  });

  b_aExtent = d3.extent(data, function(d) {return d.b_a});
  o_aExtent = d3.extent(data, function(d) {return d.o_a});

  chartExtent = ([Math.min(b_aExtent[0],o_aExtent[0]) - 5, Math.max(b_aExtent[1],o_aExtent[1]) + 5]);

  xScale = d3.scale.linear().domain([data.length, 0]).range([20,480]);
  yScale = d3.scale.linear().domain(chartExtent).range([480,20]);

  var axis = d3.svg.axis().scale(yScale)
    .orient("right")
    .ticks(8)
    .tickSize(-460)
    .tickSubdivide(true);

  b_aLine = d3.svg.line().x(function(d,i) {return xScale(i)}).y(function(d) {return yScale(d.b_a)}).interpolate("linear");
  o_aLine = d3.svg.line().x(function(d,i) {return xScale(i)}).y(function(d) {return yScale(d.o_a)}).interpolate("linear");

  b_aDifference = d3.svg.area().x(function(d,i) {return xScale(i)})
  .y(function(d) {return yScale(Math.max(d.b_a,d.o_a))})
  .y0(function(d) {return yScale(d.o_a)})
  .interpolate("linear");
  
  o_aDifference = d3.svg.area().x(function(d,i) {return xScale(i)})
  .y(function(d) {return yScale(Math.max(d.o_a,d.b_a))})
  .y0(function(d) {return yScale(d.b_a)})
  .interpolate("linear");

  linechart.append("g").attr("transform", "translate(480,0)").call(axis);

  linechart.append("path")
  .style("fill", "green")
  .style("fill-opacity", .5)
  .attr("class", "difference")
  .attr("d", b_aDifference(data))

  linechart.append("path")
  .style("fill", "red")
  .style("fill-opacity", .5)
  .attr("class", "difference")
  .attr("d", o_aDifference(data))

  linechart.append("path")
  .style("fill", "none")
  .style("stroke-width", "1px")
  .style("stroke", "darkgreen")
  .attr("class", "line")
  .attr("d", b_aLine(data))

  linechart.append("path")
  .style("fill", "none")
  .style("stroke-width", "1px")
  .style("stroke", "darkred")
  .attr("class", "line")
  .attr("d", o_aLine(data))
}

</script>

bush_obama.json

[{"o_a":48,"o_d":48,"b_a":38,"b_d":58},{"o_a":45,"o_d":51,"b_a":34,"b_d":62},{"o_a":47,"o_d":48,"b_a":35,"b_d":61},{"o_a":47,"o_d":49,"b_a":33,"b_d":63},{"o_a":44,"o_d":51,"b_a":37,"b_d":59},{"o_a":47,"o_d":49,"b_a":32,"b_d":65},{"o_a":46,"o_d":49,"b_a":36,"b_d":61},{"o_a":48,"o_d":47,"b_a":34,"b_d":63},{"o_a":46,"o_d":49,"b_a":37,"b_d":59},{"o_a":45,"o_d":49,"b_a":35,"b_d":61},{"o_a":45,"o_d":50,"b_a":38,"b_d":59},{"o_a":43,"o_d":52,"b_a":33,"b_d":62},{"o_a":43,"o_d":52,"b_a":38,"b_d":56},{"o_a":42,"o_d":53,"b_a":37,"b_d":58},{"o_a":43,"o_d":52,"b_a":37,"b_d":57},{"o_a":40,"o_d":54,"b_a":37,"b_d":59},{"o_a":42,"o_d":53,"b_a":44,"b_d":51},{"o_a":41,"o_d":54,"b_a":39,"b_d":56},{"o_a":41,"o_d":54,"b_a":42,"b_d":54},{"o_a":43,"o_d":52,"b_a":37,"b_d":59},{"o_a":42,"o_d":53,"b_a":40,"b_d":56},{"o_a":41,"o_d":53,"b_a":37,"b_d":59},{"o_a":41,"o_d":52,"b_a":40,"b_d":55},{"o_a":42,"o_d":51,"b_a":37,"b_d":60},{"o_a":41,"o_d":53,"b_a":38,"b_d":56},{"o_a":41,"o_d":53,"b_a":36,"b_d":57},{"o_a":42,"o_d":52,"b_a":33,"b_d":61},{"o_a":43,"o_d":52,"b_a":31,"b_d":65},{"o_a":42,"o_d":52,"b_a":34,"b_d":63},{"o_a":41,"o_d":53,"b_a":36,"b_d":59},{"o_a":41,"o_d":54,"b_a":37,"b_d":60},{"o_a":44,"o_d":51,"b_a":37,"b_d":59},{"o_a":44,"o_d":51,"b_a":36,"b_d":60},{"o_a":44,"o_d":51,"b_a":38,"b_d":60},{"o_a":44,"o_d":51,"b_a":39,"b_d":56},{"o_a":44,"o_d":51,"b_a":42,"b_d":55},{"o_a":44,"o_d":49,"b_a":43,"b_d":54},{"o_a":44,"o_d":51,"b_a":43,"b_d":53},{"o_a":43,"o_d":52,"b_a":43,"b_d":54},{"o_a":43,"o_d":52,"b_a":43,"b_d":53},{"o_a":43,"o_d":53,"b_a":41,"b_d":56},{"o_a":42,"o_d":54,"b_a":42,"b_d":55},{"o_a":44,"o_d":51,"b_a":43,"b_d":52},{"o_a":41,"o_d":51,"b_a":38,"b_d":57},{"o_a":42,"o_d":50,"b_a":37,"b_d":60},{"o_a":42,"o_d":50,"b_a":40,"b_d":55},{"o_a":42,"o_d":51,"b_a":41,"b_d":56},{"o_a":42,"o_d":51,"b_a":41,"b_d":56},{"o_a":40,"o_d":52,"b_a":42,"b_d":55},{"o_a":41,"o_d":51,"b_a":39,"b_d":58},{"o_a":42,"o_d":52,"b_a":45,"b_d":50},{"o_a":40,"o_d":53,"b_a":40,"b_d":58},{"o_a":41,"o_d":52,"b_a":45,"b_d":52},{"o_a":43,"o_d":50,"b_a":46,"b_d":51},{"o_a":43,"o_d":51,"b_a":45,"b_d":52},{"o_a":44,"o_d":50,"b_a":40,"b_d":56},{"o_a":43,"o_d":50,"b_a":45,"b_d":51},{"o_a":45,"o_d":47,"b_a":45,"b_d":51},{"o_a":44,"o_d":47,"b_a":44,"b_d":51},{"o_a":44,"o_d":48,"b_a":49,"b_d":48},{"o_a":45,"o_d":47,"b_a":49,"b_d":48},{"o_a":45,"o_d":47,"b_a":46,"b_d":51},{"o_a":44,"o_d":47,"b_a":45,"b_d":53},{"o_a":45,"o_d":47,"b_a":47,"b_d":51},{"o_a":46,"o_d":47,"b_a":47,"b_d":49},{"o_a":46,"o_d":47,"b_a":48,"b_d":47},{"o_a":46,"o_d":46,"b_a":46,"b_d":50},{"o_a":47,"o_d":45,"b_a":50,"b_d":45},{"o_a":47,"o_d":45,"b_a":48,"b_d":49},{"o_a":48,"o_d":44,"b_a":48,"b_d":49},{"o_a":50,"o_d":44,"b_a":50,"b_d":45},{"o_a":49,"o_d":45,"b_a":48,"b_d":48},{"o_a":50,"o_d":44,"b_a":45,"b_d":49},{"o_a":51,"o_d":43,"b_a":52,"b_d":44},{"o_a":49,"o_d":45,"b_a":52,"b_d":44},{"o_a":49,"o_d":44,"b_a":52,"b_d":45},{"o_a":48,"o_d":46,"b_a":51,"b_d":45},{"o_a":47,"o_d":45,"b_a":49,"b_d":48},{"o_a":48,"o_d":45,"b_a":57,"b_d":40},{"o_a":49,"o_d":44,"b_a":51,"b_d":46},{"o_a":51,"o_d":42,"b_a":52,"b_d":44},{"o_a":51,"o_d":43,"b_a":52,"b_d":44},{"o_a":52,"o_d":42,"b_a":49,"b_d":46},{"o_a":52,"o_d":42,"b_a":53,"b_d":44},{"o_a":50,"o_d":43,"b_a":55,"b_d":42},{"o_a":54,"o_d":41,"b_a":53,"b_d":44},{"o_a":56,"o_d":38,"b_a":48,"b_d":47},{"o_a":52,"o_d":41,"b_a":51,"b_d":46},{"o_a":51,"o_d":43,"b_a":51,"b_d":47},{"o_a":51,"o_d":41,"b_a":48,"b_d":49},{"o_a":52,"o_d":41,"b_a":47,"b_d":49},{"o_a":51,"o_d":43,"b_a":50,"b_d":48},{"o_a":50,"o_d":45,"b_a":54,"b_d":44},{"o_a":50,"o_d":44,"b_a":52,"b_d":45},{"o_a":50,"o_d":44,"b_a":52,"b_d":46},{"o_a":48,"o_d":45,"b_a":49,"b_d":47},{"o_a":50,"o_d":43,"b_a":51,"b_d":46},{"o_a":49,"o_d":45,"b_a":48,"b_d":49},{"o_a":46,"o_d":48,"b_a":49,"b_d":47},{"o_a":45,"o_d":49,"b_a":47,"b_d":49},{"o_a":45,"o_d":49,"b_a":48,"b_d":49},{"o_a":46,"o_d":48,"b_a":49,"b_d":49},{"o_a":46,"o_d":47,"b_a":47,"b_d":49},{"o_a":45,"o_d":47,"b_a":46,"b_d":51},{"o_a":47,"o_d":46,"b_a":49,"b_d":48},{"o_a":45,"o_d":48,"b_a":52,"b_d":45},{"o_a":47,"o_d":46,"b_a":52,"b_d":45},{"o_a":47,"o_d":46,"b_a":53,"b_d":44},{"o_a":47,"o_d":46,"b_a":50,"b_d":47},{"o_a":47,"o_d":47,"b_a":49,"b_d":48},{"o_a":49,"o_d":46,"b_a":51,"b_d":46},{"o_a":48,"o_d":45,"b_a":51,"b_d":46},{"o_a":47,"o_d":47,"b_a":52,"b_d":44},{"o_a":46,"o_d":46,"b_a":49,"b_d":48},{"o_a":47,"o_d":45,"b_a":53,"b_d":44},{"o_a":46,"o_d":47,"b_a":59,"b_d":38},{"o_a":46,"o_d":47,"b_a":60,"b_d":35},{"o_a":45,"o_d":48,"b_a":63,"b_d":34},{"o_a":45,"o_d":48,"b_a":56,"b_d":41},{"o_a":46,"o_d":47,"b_a":55,"b_d":43},{"o_a":45,"o_d":48,"b_a":50,"b_d":47},{"o_a":45,"o_d":46,"b_a":51,"b_d":45},{"o_a":46,"o_d":46,"b_a":54,"b_d":43},{"o_a":44,"o_d":48,"b_a":53,"b_d":42},{"o_a":42,"o_d":50,"b_a":56,"b_d":40},{"o_a":42,"o_d":50,"b_a":55,"b_d":42},{"o_a":43,"o_d":49,"b_a":50,"b_d":47},{"o_a":43,"o_d":49,"b_a":52,"b_d":43},{"o_a":43,"o_d":50,"b_a":59,"b_d":37},{"o_a":43,"o_d":50,"b_a":60,"b_d":36},{"o_a":41,"o_d":51,"b_a":58,"b_d":38},{"o_a":40,"o_d":52,"b_a":59,"b_d":38},{"o_a":41,"o_d":51,"b_a":62,"b_d":34},{"o_a":41,"o_d":51,"b_a":61,"b_d":36},{"o_a":43,"o_d":49,"b_a":63,"b_d":33},{"o_a":40,"o_d":52,"b_a":62,"b_d":34},{"o_a":40,"o_d":52,"b_a":64,"b_d":32},{"o_a":41,"o_d":50,"b_a":66,"b_d":30},{"o_a":42,"o_d":51,"b_a":69,"b_d":28},{"o_a":44,"o_d":48,"b_a":70,"b_d":26},{"o_a":45,"o_d":46,"b_a":71,"b_d":24},{"o_a":46,"o_d":46,"b_a":69,"b_d":26},{"o_a":45,"o_d":48,"b_a":70,"b_d":27},{"o_a":46,"o_d":46,"b_a":71,"b_d":26},{"o_a":49,"o_d":43,"b_a":69,"b_d":27},{"o_a":50,"o_d":42,"b_a":71,"b_d":25},{"o_a":48,"o_d":43,"b_a":58,"b_d":38},{"o_a":51,"o_d":40,"b_a":57,"b_d":37},{"o_a":46,"o_d":46,"b_a":57,"b_d":37},{"o_a":43,"o_d":48,"b_a":58,"b_d":37},{"o_a":45,"o_d":46,"b_a":61,"b_d":34},{"o_a":47,"o_d":45,"b_a":59,"b_d":35},{"o_a":46,"o_d":46,"b_a":61,"b_d":35},{"o_a":48,"o_d":44,"b_a":60,"b_d":36},{"o_a":47,"o_d":45,"b_a":58,"b_d":36},{"o_a":46,"o_d":46,"b_a":61,"b_d":34},{"o_a":48,"o_d":44,"b_a":58,"b_d":37},{"o_a":48,"o_d":44,"b_a":63,"b_d":32},{"o_a":48,"o_d":44,"b_a":61,"b_d":32},{"o_a":50,"o_d":42,"b_a":63,"b_d":33},{"o_a":49,"o_d":43,"b_a":63,"b_d":32},{"o_a":48,"o_d":45,"b_a":64,"b_d":29},{"o_a":45,"o_d":47,"b_a":65,"b_d":28},{"o_a":45,"o_d":47,"b_a":66,"b_d":26},{"o_a":46,"o_d":46,"b_a":68,"b_d":27},{"o_a":45,"o_d":47,"b_a":63,"b_d":29},{"o_a":45,"o_d":47,"b_a":67,"b_d":28},{"o_a":45,"o_d":48,"b_a":62,"b_d":31},{"o_a":45,"o_d":47,"b_a":67,"b_d":28},{"o_a":46,"o_d":48,"b_a":68,"b_d":26},{"o_a":46,"o_d":47,"b_a":66,"b_d":30},{"o_a":46,"o_d":47,"b_a":70,"b_d":26},{"o_a":46,"o_d":47,"b_a":66,"b_d":30},{"o_a":45,"o_d":47,"b_a":66,"b_d":29},{"o_a":43,"o_d":50,"b_a":65,"b_d":28},{"o_a":43,"o_d":49,"b_a":68,"b_d":26},{"o_a":45,"o_d":48,"b_a":71,"b_d":23},{"o_a":45,"o_d":47,"b_a":69,"b_d":26},{"o_a":46,"o_d":46,"b_a":69,"b_d":24},{"o_a":46,"o_d":47,"b_a":73,"b_d":21},{"o_a":46,"o_d":46,"b_a":76,"b_d":18},{"o_a":47,"o_d":45,"b_a":76,"b_d":19},{"o_a":46,"o_d":47,"b_a":73,"b_d":21},{"o_a":46,"o_d":46,"b_a":74,"b_d":20},{"o_a":48,"o_d":45,"b_a":74,"b_d":18},{"o_a":51,"o_d":42,"b_a":70,"b_d":23},{"o_a":50,"o_d":43,"b_a":77,"b_d":17},{"o_a":48,"o_d":45,"b_a":76,"b_d":17},{"o_a":47,"o_d":46,"b_a":76,"b_d":19},{"o_a":49,"o_d":44,"b_a":77,"b_d":20},{"o_a":49,"o_d":44,"b_a":77,"b_d":17},{"o_a":47,"o_d":45,"b_a":75,"b_d":20},{"o_a":50,"o_d":43,"b_a":76,"b_d":19},{"o_a":49,"o_d":43,"b_a":79,"b_d":17},{"o_a":52,"o_d":41,"b_a":79,"b_d":16},{"o_a":49,"o_d":45,"b_a":80,"b_d":14},{"o_a":48,"o_d":46,"b_a":77,"b_d":18},{"o_a":50,"o_d":43,"b_a":81,"b_d":14},{"o_a":51,"o_d":43,"b_a":82,"b_d":14},{"o_a":50,"o_d":44,"b_a":82,"b_d":14},{"o_a":49,"o_d":42,"b_a":84,"b_d":13},{"o_a":50,"o_d":43,"b_a":83,"b_d":13},{"o_a":49,"o_d":44,"b_a":84,"b_d":12},{"o_a":52,"o_d":40,"b_a":86,"b_d":11},{"o_a":53,"o_d":40,"b_a":86,"b_d":10},{"o_a":52,"o_d":40,"b_a":87,"b_d":8},{"o_a":52,"o_d":41,"b_a":87,"b_d":9},{"o_a":52,"o_d":40,"b_a":87,"b_d":9},{"o_a":51,"o_d":41,"b_a":88,"b_d":9},{"o_a":52,"o_d":41,"b_a":89,"b_d":8},{"o_a":53,"o_d":40,"b_a":87,"b_d":10},{"o_a":51,"o_d":42,"b_a":90,"b_d":6},{"o_a":52,"o_d":40,"b_a":86,"b_d":10},{"o_a":56,"o_d":37,"b_a":51,"b_d":39},{"o_a":54,"o_d":39,"b_a":55,"b_d":36},{"o_a":57,"o_d":37,"b_a":57,"b_d":34},{"o_a":58,"o_d":35,"b_a":57,"b_d":35},{"o_a":60,"o_d":32,"b_a":55,"b_d":35},{"o_a":59,"o_d":34,"b_a":56,"b_d":33},{"o_a":61,"o_d":32,"b_a":57,"b_d":35},{"o_a":63,"o_d":30,"b_a":52,"b_d":34},{"o_a":64,"o_d":28,"b_a":55,"b_d":33},{"o_a":65,"o_d":28,"b_a":55,"b_d":35},{"o_a":67,"o_d":27,"b_a":56,"b_d":36},{"o_a":64,"o_d":29,"b_a":56,"b_d":31},{"o_a":62,"o_d":29,"b_a":53,"b_d":33},{"o_a":61,"o_d":28,"b_a":62,"b_d":29},{"o_a":61,"o_d":29,"b_a":59,"b_d":30},{"o_a":62,"o_d":28,"b_a":53,"b_d":29},{"o_a":62,"o_d":27,"b_a":58,"b_d":29},{"o_a":64,"o_d":24,"b_a":63,"b_d":22},{"o_a":64,"o_d":22,"b_a":62,"b_d":21},{"o_a":65,"o_d":20,"b_a":57,"b_d":25},{"o_a":66,"o_d":17,"b_a":57,"b_d":25}]