Change two axes in D3 Scatterplot

The original scatterplot that I used for my own purposes projected values on one axis. The ‘What makes us happy?’ visualization shows correlation between well-being and various socioeconomic aspects, but the y-axis (well-being) always remains the same.

However, when I wanted to show how BI vendors fared in Gartner’s 2013 and 2014 reports, I had to change the values on both scales. Much to my surprise there wasn’t a solution out there, so I thought I share my own version of changing both axes individually or simultaneously on the same chart.

1. Changing each dimension separately:

Obviously, you will create the appropriate placeholders and formatting:

<div id="menu"> <!-- the comments are D3 placeholders -->
   <!--<h2>&uarr; Y axis</h2>--> <ul id="y-axis-menu"></ul>
   <!--<h2>&rarr; X axis</h2>--> <ul id="x-axis-menu"></ul>
</div>

And define the axes separately in D3:

var xAxis = 'GDP', yAxis = 'Well-being';
var xAxisOptions = ["Well-being" , "GDP", "Equality", "Food consumption", "Alcohol consumption", "Energy consumption", "Family", "Working hours", "Work income", "Health spending", "Military spending"]
var yAxisOptions = ["Well-being", "Equality"];

On click, the axes will change separately, so you’ll have to click twice:

d3.select('#x-axis-menu')
    .selectAll('li')
    .data(xAxisOptions)
    .enter()
    .append('li')
    .text(function(d) {return d;})
    .classed('selected', function(d) {
      return d === xAxis;
    })
    .on('click', function(d) {
      xAxis = d;
      updateChart();
      updateMenus();
    });

Then just do the same for the y-axis.

d3.select('#y-axis-menu')
    .selectAll('li')
    .data(yAxisOptions)
    .enter()
    .append('li')
    .text(function(d) {return d;})
    .classed('selected', function(d) {
      return d === yAxis;
    })
    .on('click', function(d) {
      yAxis = d;
      updateChart();
      updateMenus();
    });

The axes labels are changed with each click, too:

  // Axis labels
  d3.select('svg g.chart')
    .append('text')
    .attr({'id': 'xLabel', 'x': 400, 'y': 670, 'text-anchor': 'middle'})
    .text(descriptions[xAxis]);

  d3.select('svg g.chart')
    .append('text')
    .attr('transform', 'translate(-60, 330)rotate(-90)')
    .attr({'id': 'yLabel', 'text-anchor': 'middle'})
    .text(descriptions[xAxis]);

The data for this exercise should look like this:

Country,  Well-being,  GDP,         Equality, ... etc. 
Austria,     5.37,     26171.6909,  70.85, ... etc. 
Belgium,     5.04,     24512.4131,  67.03, ... etc. 
Bulgaria,    4.59,     2332.3631,   69.416666, ... etc.

With other words, both axes are in the header row, and the values are below. Here is my working example.

2. Change both axes at the same time.
The DOM (and CSS) doens’t change, you can copy that from above.
The axes’ definition is somewhat different, since I’m plotting the Gartner report, not country data:

  var xAxis = '2013x', yAxis = '2013y';
  var xAxisOptions = ["2013" , "2014"]
  var descriptions = {
    "2013x" : "Vision in 2013",
    "2013y" : "Execution in 2013",
    "2014x" : "Vision in 2014",
    "2014y" : "Execution in 2014"
  };

The menu build has to be merged into one segment, since the same mouse click will change both axes:

  // Build menus
  d3.select('#x-axis-menu')
    .selectAll('li')
    .data(xAxisOptions)
    .enter()
    .append('li')
    .text(function(d) {return d;})
    .classed('selected', function(d) {
      return d === xAxis;
      return d === yAxis;
    })
    .on('click', function(d) {
      xAxis = d + "x";
      yAxis = d + "y";
      updateChart();
      updateMenus();
    });

To make sure this solution works, you have to label your data appropriately:

Company,    2013x,  2013y,   2014x,   2014y
Microsoft,   68,     81,      64,      69
Tableau,     52,     79,      63,      78
QlikTech,    58,     76,      63,      70

See? Because D3 is a little crippled on the matter of changing two axes simultaneously, you have to meet it half-way, and do half the work yourself with the labels. Here is the working example.

Conclusion: You can change axes in D3 all day long. Above are two examples for you.