Introduction to D3

Marcos Iglesias

Eventbrite Logo

Online

Next up

  • Introduction
  • Applications
  • Bar Chart Example
  • D3 Selection
  • Live coding

What is D3.js?

  • Data-Driven Documents
  • General Purpose Visualization Library
  • Manipulates data based documents
  • Open web standards (SVG, HTML, CSS and now Canvas)
  • Allows interactions with your graphs

How does it work?

  • Loads data
  • Binds data to elements
  • Transforms those elements
  • Transitions between states
  • Example

D3 Niceties

  • Based on attaching data to the DOM
  • Styling of elements with CSS
  • Transitions and animations baked in
  • Total control over our graphs
  • Amazing community
  • Decent amount of publications

D3 v4 Update

  • More modular
  • Breaking changes
  • New standard

What can you do with D3?

Bar charts

Bar Chart

Pie charts

Pie Chart

Bubble charts

Bubble Chart

Choropleth

Map projections

Dashboards

Algorithm visualization

Hierarchical Edge Bundling

Artistic visualizations

Pie Chart

Interactive data explorations

Obama Budget Proposal

Code example

Bar chart example by Mike Bostock

Creating container


var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var svg = d3.select("body").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 + ")");
                        

Reference: Margin Convention

Setting up scales and axes


var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);

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")
    .ticks(10, "%");
                        

Reference: Scales tutorial

Loading data


// Loads Data
d3.tsv("data.tsv", type, function(error, data) {
  if (error) throw error;
  // Chart Code here
});

// Cleans Data
function type(d) {
  d.frequency = +d.frequency;
  return d;
}
                        

Drawing axes


// Rest of the scales
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

// Draws X axis
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

// Draws Y axis
svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
  .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Frequency");
                        

Drawing bars


svg.selectAll(".bar")
    .data(data)
  .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) { return x(d.letter); })
    .attr("width", x.rangeBand())
    .attr("y", function(d) { return y(d.frequency); })
    .attr("height", function(d) { return height - y(d.frequency); });
                        

Reference: Thinking with joins, General Update Pattern

Output

Final code


var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);

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")
    .ticks(10, "%");

var svg = d3.select("body").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 + ")");

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

  x.domain(data.map(function(d) { return d.letter; }));
  y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Frequency");

  svg.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.letter); })
      .attr("width", x.bandWidth())
      .attr("y", function(d) { return y(d.frequency); })
      .attr("height", function(d) { return height - y(d.frequency); });
});

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

D3 Selections

Transform the DOM by selecting elements and joining to data

Selections

  • Subclass of array
  • Provides methods to create and manipulate selected elements
  • Array of arrays of elements

Setup


// We have some random info
let data = 'randomStringToCreateAnArray'.split('');
                        

Simplest Selection


// We create the root list element
let list = d3.select('.js-container')
                .append('ul');
                        

Data Join


let dataJoin = list.selectAll('.item')
// an empty selection, since the list container was empty
// looking for instantiations of data
                      .data(data);
                    // data, which would be bound to a
                    // selection
                        

Update, Enter and Exit Pattern

Functions that set properties

  • .text()
  • .property()
  • .style()
  • .attr()

Update


dataJoin.attr('class', 'update');

dataJoin
    .attr('foo', function(d) {
      return d.foo;
    });
                        

Enter


// for every time that we see data
// but we do not see an element
dataJoin.enter()
  .append('li').classed('enter', true)
  // we create an element
.merge(dataJoin)
    // we merge the update and enter groups and apply an operation
    .text(function(d) { return d; });
                        

Exit


// Remove all elements as needed
dataJoin.exit().remove();
                        

Resources

Live Coding

List Example

Table Example

Learning resources

Block Explorer

Block Search

Books

More

Conclusions

  • D3 is a visualization library
  • You can do amazing things with it
  • Data Joins are complex
  • but not too much...

Thanks for listening!