Search code examples
javascriptd3.jsplottable

Basic math 101 scatter plot with Plottable.js


How does one make a basic scatter plot like the one below using Plottable.js?

  • Is there something wrong with my JSON?
  • How to reveal the minus scales?
  • Would you have done anything else differently?

Style doesn't matter, the default Plottable.js one is fine.

enter image description here

window.onload = function() {
  var coordinates = [
    {
      x:"-5", 
      y:"3"
    }, {
      x:"2", 
      y:"-1,5"
    }, {
      x:"5", 
      y:"2,5"
    }
  ];
  
  var xScale = new Plottable.Scale.Linear();
  var yScale = new Plottable.Scale.Linear();
  var colorScale = new Plottable.Scale.Color("10");

  var xAxis = new Plottable.Axis.Numeric(xScale, "bottom");
  var yAxis = new Plottable.Axis.Numeric(yScale, "left");

  var plot = new Plottable.Plot.Scatter(xScale, yScale)
                      .addDataset(coordinates)
                      .project("x", "", xScale)
                      .project("y", "", yScale)
                      .project("fill", "", colorScale);
  
  var chart = new Plottable.Component.Table([
      [yAxis, plot],
      [null,  xAxis]
  ]);

  chart.renderTo("#my_chart");
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
    <link rel="stylesheet" href="https://rawgit.com/palantir/plottable/develop/plottable.css">
  </head>
  <body>
    <svg width="100%" height="600" id="my_chart"></svg>
    <script src="https://rawgit.com/mbostock/d3/master/d3.min.js"></script>
    <script src="https://rawgit.com/palantir/plottable/develop/plottable.min.js"></script>
  </body>
</html>


Solution

  • Here's a couple examples I just put together. The first is the straight d3 way of doing what you are asking. The second is a hacked up plottable.js. With plottable.js I can't find a way to position the axis outside of their table system, I had to resort to manually moving them. The table system they use is designed to relieve the developer of having to manually position things. This is great and easy, of course, until you want to control where to position things.

    Here's the hack, after you render your plottable:

      // move the axis...
      d3.select(".y-axis")
        .attr('transform',"translate(" + width / 2 + "," + 0 + ")");        
      d3.select(".x-axis")
        .attr("transform", "translate(" + 48 + "," + height / 2 + ")");
    

    Note, I didn't remove the left side margin (the 48 above) that plottable puts in. This could be hacked in as well, but at that point, what is plottable providing for you anyway...

    It should be noted that the different appearance of each plot is entirely controlled through the CSS.

    Complete d3 scatter plot:

    // D3 EXAMPLE
    var margin = {
      top: 20,
      right: 20,
      bottom: 20,
      left: 20
    },
      width = 500 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;
    
    var x = d3.scale.linear()
      .range([0, width]);
    
    var y = d3.scale.linear()
      .range([height, 0]);
    
    var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom");
    
    var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left");
    
    var svg = d3.select("#d3").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 + ")");
    
    x.domain([-100, 100]);
    y.domain([-100, 100]);
    
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(" + 0 + "," + height / 2 + ")")
      .call(xAxis);
    
    svg.append("g")
      .attr("class", "y axis")
      .attr("transform", "translate(" + width / 2 + "," + 0 + ")")
      .call(yAxis)
      .append("text");
    
    svg.selectAll(".dot")
      .data(data)
      .enter().append("circle")
      .attr("class", "dot")
      .attr("r", function(d) {
        return d.r;
      })
      .attr("cx", function(d) {
        return x(d.x);
      })
      .attr("cy", function(d) {
        return y(d.y);
      })
      .style("fill", function(d) {
        return d.c;
      });
    

    enter image description here

    Plottable.js:

      // PLOTTABLE.JS
      var xScale = new Plottable.Scale.Linear();
      var yScale = new Plottable.Scale.Linear();
    
      var xAxis = new Plottable.Axis.Numeric(xScale, "bottom");
      var yAxis = new Plottable.Axis.Numeric(yScale, "left");
    
      var plot = new Plottable.Plot.Scatter(xScale, yScale);
      plot.addDataset(data);
    
      function getXDataValue(d) {
        return d.x;
      }
      plot.project("x", getXDataValue, xScale);
      function getYDataValue(d) {
        return d.y;
      }
      plot.project("y", getYDataValue, yScale);
      function getRDataValue(d){
        return d.r;
      }
      plot.project("r", getRDataValue);
      function getFillValue(d){
        return d.c;
      }
      plot.project("fill", getFillValue);
      var chart = new Plottable.Component.Table([
                        [yAxis, plot],
                        [null,  xAxis]
                      ]);
      chart.renderTo("#plottable");
    
      d3.select(".y-axis")
        .attr('transform',"translate(" + width / 2 + "," + 0 + ")");
    
      d3.select(".x-axis")
        .attr("transform", "translate(" + 48 + "," + height / 2 + ")");
    

    enter image description here