In [1]:
!date
Sat Apr 20 14:23:24 PDT 2013

Three ways to make the "hello, world" of statistical graphics

In [56]:
# load js libraries
from IPython.core.display import display, HTML, Javascript
display(HTML("""
<script src="http://trifacta.github.com/vega/d3.v3.min.js"></script>
<script src="http://trifacta.github.com/vega/vega.js"></script>
"""))

D3 is hardest

In [57]:
# css for axis
display(HTML("""
<style type="text/css">
  .axis path,
  .axis line {
    fill: none;
    stroke: black;
    shape-rendering: crispEdges;
  }
  .axis text {
    font-family: sans-serif;
    font-size: 11px;
  }
</style>
"""))
In [58]:
%%javascript
// Make visible in IPython 
container.show()

//Width and height
var w = 500;
var h = 300;
var padding = 30;

//Create svg in IPython element
var svg = d3.selectAll(element).append('svg').attr('width', w).attr('height', h); 

//Initialize data array
var dataset = [3,1,4,1,5,9];

//Create scale functions
var xScale = d3.scale.linear()
                     .domain([-.5, d3.max(dataset, function(d,i) { return i; })])
                     .range([padding, w - padding * 2]);

var yScale = d3.scale.linear()
                     .domain([-.5, d3.max(dataset, function(d) { return d; })])
                     .range([h - padding, padding]);

//Define X axis
var xAxis = d3.svg.axis()
                  .scale(xScale)
                  .orient("bottom")
                  .ticks(5);

//Define Y axis
var yAxis = d3.svg.axis()
                  .scale(yScale)
                  .orient("left")
                  .ticks(10);

//Create circles
svg.selectAll("circle")
   .data(dataset)
   .enter()
   .append("circle")
   .attr("cx", function(d,i) {
        return xScale(i);
   })
   .attr("cy", function(d) {
        return yScale(d);
   })
   .attr("r", 5);

var line = d3.svg.line()
    .x(function(d,i) { return xScale(i); })
    .y(function(d) { return yScale(d); });

svg.append("svg:path").attr("d", line(dataset)).attr("fill", "none").attr("stroke", "black");

//Create X axis
svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(0," + (h - padding) + ")")
    .call(xAxis);

//Create Y axis
svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + padding + ",0)")
    .call(yAxis);

Vega is easier, but requires writing JSON by hand

No humans should have to write JSON by hand

In [74]:
display(HTML("""<div id="vega"></div>"""),
        Javascript("""
var spec = {
  "width": 500, 
  "height": 300, 
  "padding": {"top": 10, "bottom": 20, "right": 10, "left": 30}, 
  "data": [
    {
      "values": [{"x": 0, "y": 3}, {"x": 1, "y": 1}, {"x": 2, "y": 4}, {"x": 3, "y": 1}, {"x": 4, "y": 5}, {"x": 5, "y": 9}], 
      "name": "table"
    }
  ], 

  "scales": [
    {
      "name": "x", 
      "type": "linear", 
      "domain": {"field": "data.x", "data": "table"},
      "range": "width"
    }, 
    {
      "name": "y", 
      "domain": {"field": "data.y", "data": "table"}, 
      "range": "height", 
      "nice": true
    }
  ], 
  "axes": [
    {"scale": "x", "type": "x"}, 
    {"scale": "y", "type": "y"}
  ], 
  "marks": [
    {
      "type": "line", 
      "from": {"data": "table"}, 
      "properties": {
        "enter": {
          "x": {"field": "data.x", "scale": "x"},
          "y": {"field": "data.y", "scale": "y"}, 
          "y2": {"scale": "y", "value": 0},
          "stroke": {"value": "#000000"}
        }
      }
    }, 
    {
      "type": "symbol", 
      "from": {"data": "table"}, 
      "properties": {
        "update": {
          "fill": {"value": "#2a3140"}
        }, 
        "enter": {
          "x": {"field": "data.x", "scale": "x"},
          "y": {"field": "data.y", "scale": "y"}, 
          "stroke": {"value": "#ffffff"},
          "strokeWidth": {"value": 2}          
        }
      }
    }
  ]
}
;
vg.parse.spec(spec, function(chart) { chart({el:"#vega"}).update(); });
"""))

Vincent is easiest

In [75]:
import vincent
def vincent_ipynb_display(vis):
    import json, random
    from IPython.core.display import display, HTML, Javascript

    # HACK: use a randomly chosen unique div id
    id = random.randint(0, 2**16)
    
    a = HTML("""
        <div id="vis%d"></div>
        """ % id)

    b = Javascript("""
        vg.parse.spec(%s, function(chart) { chart({el:"#vis%d"}).update(); });
        """ % (json.dumps(vis.vega), id))
    
    display(a, b)
In [76]:
vis = vincent.Line()
vis.tabular_data([3,1,4,1,5,9])

vis2 = vincent.Scatter()
vis2.tabular_data([3,1,4,1,5,9])

vis.marks += vis2.marks

vincent_ipynb_display(vis)
In [ ]: