William Cai

DATA-DRIVEN DOCUMENTS

Mike Bostock

mbostock

The New York Times

San Francisco, CA

http://bost.ocks.org

Jason Davies

jasondavies

Jason Davies Ltd

London, UK

http://www.jasondavies.com

a chart library

Not

a map library

a compatibility layer

about SVG or HTML or Canvas

Though you can make charts with it
Though you can make maps with it 
It doesn't work with bad browsers 
Though you can use it with them 

What is D3 ?

Not

Not

Not

design motivations

Visualizing Data with Web Standards

A central tenet of D3 is to make visualization easier without introducing a new way of representing an image. D3 uses existing standards — namely HTML and SVG.

This approach offers a whole host of benefits, including greater expressiveness, future-proofing, and compatibility with existing tools and technologies, such as CSS and debuggers.

D3 provides transformation; no new representation.

design motivations

Data ↦ Elements

Since D3 does not provide new representa­tion, the task of visualization is constructing a DOM from data. We must also update the DOM whenever the data changes, either due to dynamic (e.g., realtime) data or interaction.

In a visualization, each entity (or data point) has a corresponding element (or graphical mark). D3 helps you maintain this mapping from data to elements.

Visualization requires visual encoding: mapping data to elements.

design motivations

Data-Driven Documents

The name “D3” refers to the W3C Document Object Model.

Web Standards

“Learning D3” is largely learning web standards. Fortunately, there are lots of resources for learning standards!

HTML Resources

MDN

Specs are good for reference, but a bit overwhelming if you’re not sure where to start. Specs can be more helpful for understanding interesting techniques found in the wild.

<!DOCTYPE html>
<meta charset="utf-8">
<body>
Hello, world!

Showing the beauty of minimalist HTML5 markup. All those extraneous tags? Poof!

SVG Resources

MDN

SVG lets you draw vector graphics in the browser, allowing much greater expressiveness than HTML. You can do some stuff (like simple bar charts and input controls) using only HTML, but mostly you’ll want to use SVG to visualize data.

<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500">
  <text y="12">
    Hello, world!
  </text>
</svg>

You can embed SVG directly inside HTML, much like an image tag. Of course, if you’re using D3 for data visualization, the SVG will more often be constructed by JavaScript. Sometimes you might have static bits of SVG; you can always modify it later.

CSS Resources

Unlike HTML and SVG, CSS doesn’t introduce new representation; it’s just a way of adding aesthetics and presentation (such as colors and fonts). CSS greatly simplifies your code, so I highly recommend it!
For example, rather than assigning colors explicitly via JavaScript, assign a class. Then you can easily change the definition or apply multiple styles simultaneously.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  body { background: steelblue; }
</style>
<body>
Hello, world!

JavaScript Resources

MDN

If beauty is in the eye of the beholder, JavaScript is a beautiful language. D3 uses some functional idioms (lots of closures and higher-order programming). These concepts can be unfamiliar but are very elegant and powerful. If you’re unsure how some piece of D3 code works, reading about these language features may help.

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script>
  console.log("Hello, world!");
</script>

D3 Resources

Although not as established as standards, there are still many available resources for learning D3, including a variety of contributed tutorials and talks.
Make use of the d3-js group! I answer support questions nearly everyday and love to hear from you. Unless you are angry. In which case you should enjoy some time outside.

Selections of elements are D3’s atomic operand.

The basic idea is familiar to you already if you know jQuery.

Selections

Selectors

CSS provides a handy way to refer to specific elements.

pre, code {
  font-family: "Menlo", monospace;
  font-size: 48px;
}

CSS assigns style rules via selectors.

This snippet applies two style properties (setting the font family and size) to all <pre> and <code> elements. CSS is a declarative language for assigning styles to elements.

Selectors

#foo        // <any id="foo">
foo         // <foo>
.foo        // <any class="foo">
[foo=bar]   // <any foo="bar">
foo bar     // <foo><bar></foo>

Selectors

Simple selectors identify elements by one facet.

Selectors

foo.bar     // <foo class="bar">
foo#bar     // <foo id="bar">

Compound selectors identify elements by two or more facets.

W3C standardized selector

document.querySelectorAll("pre, code")

The W3C standardized selector support for JavaScript.

The W3C Selectors API provides selectors, but not selections. So, you can select elements easily, yet you must iterate over them and assign attributes and styles for each. Hence the need for JavaScript libraries to make web development easier.

d3.selectAll("pre, code")

D3 provides shorthand for selecting and manipulating.

Or, in jQuery: $("pre, code").

Selections

Selections are Arrays

// select all <circle> elements
var circle = d3.selectAll("circle");

// set some attributes and styles
circle.attr("cx", 20);
circle.attr("cy", 12);
circle.attr("r", 24);
circle.style("fill", "red");

One thing to note: numbers and other values are automatically coerced to strings when setting attributes and styles. So, you don’t have to do that yourself (which is nice), and you can also use helper classes such as d3.rgb and d3.hsl.

The attr and style methods set attributes and styles, respectively.

Selections are Arrays

// select all <circle> elements
// and set some attributes and styles
d3.selectAll("circle")
    .attr("cx", 20)
    .attr("cy", 12)
    .attr("r", 24)
    .style("fill", "red");

Method chaining allows shorter (and more readable) code.

Selections.append

// select the <body> element
var body = d3.select("body");

// add an <h1> element
var h1 = body.append("h1");
h1.text("Hello!");

With one element selected, adds one element.

Selections.append

// select all <section> elements
var section = d3.selectAll("section");

// add an <h1> element to each
var h1 = section.append("h1");
h1.text("Hello!");

With many elements selected, adds one element to each.

Selections.append

var h1 = d3.selectAll("section")
    .style("background", "steelblue")
  .append("h1")
    .text("Hello!");

Use caution with method chaining: append returns a new selection!

With method chaining, I normally use four spaces to indent. However, I use two spaces for operations that change the selection, such as append. This causes operations that change the context to stick out.

In this snippet, the entire expression evaluates to the appended <h1> elements, even though we started by selecting <section> elements.

Add many elements?

No single operation; this brings us to our next topic…

Data are Arrays, too

You can represent data however you like (in JavaScript).

Selections are arrays. 

Coincidence? 

Nope.

Data

// A bar chart, perhaps?
var data = [1, 1, 2, 3, 5, 8];

If you want to be fancy,
you can call an array of numbers a “univariate dataset”.

Data can be numbers

Data can be numbers

// A scatterplot, perhaps?
var data = [
  {x: 10.0, y: 9.14},
  {x:  8.0, y: 8.14},
  {x: 13.0, y: 8.74},
  {x:  9.0, y: 8.77},
  {x: 11.0, y: 9.26}
];

If you want to be fancy,
you can call an array of objects a “univariate dataset”.

Data can be objects

Data can be objects

Data ↦  Elements

D3 doesn’t provide a single method for creating multiple elements; instead, it provides a pattern for managing the mapping from data to elements. The way to create elements from scratch is a special case of the more generalized form.

Use data to create multiple elements.

Data ↦  Elements

svg.selectAll("circle")
    .data(data)
  .enter().append("circle")
    .attr("cx", x)
    .attr("cy", y)
    .attr("r", 2.5);

We want the selection “circle” to correspond to data.

This common snippet creates new elements from data. The first line may be surprising—why select <circle> elements if you know they don’t exist? Well, you’re telling D3 that you want them to correspond to data.

This parsimonious approach means that when you need to handle update and exit in the future (for your interactive or dynamic visualizations), it’s a simple extension of a pattern you already know.

Data ↦  Elements

var circle = svg.selectAll("circle")
    .data(data);

The data method computes the join, defining enter and exit.

The data method does all the work. The enter and exit methods just return the subselections computed in the join.

Data ↦  Elements

var circle = svg.selectAll("circle")
    .data(data);

circle.enter().append("circle");

Appending to the enter selection creates the missing elements.

The append method on enter selections is special; it still creates one new element per selected element, but it adds them to the parent node (here the SVG element).

Data ↦  Elements

var circle = svg.selectAll("circle")
    .data(data);

circle.enter().append("circle")
    .attr("cx", x)
    .attr("cy", y)
    .attr("r", 2.5);

The new elements are bound to data, so we can compute attributes.

X and y here refer to accessor functions, such as function x(d) { return d.x; }. I couldn’t fit them on the slide. I commonly use anonymous functions to compute attributes from data.

The data join is likely the hardest concept of D3 to grasp, but it’s a powerful way of manipulating the DOM.

Enter, Update & Exit

New data, for which there were no existing elements.

Enter

When initializing, you might ignore update and exit.

var circle = svg.selectAll("circle")
    .data(data)
  .enter().append("circle")
    .attr("cx", x)
    .attr("cy", y)
    .attr("r", 2.5);

This is the same code snippet as before. In effect, we’ve simplified the general pattern by assuming there are no updating or exiting elements.

Enter

New data that was joined successfully to an existing element.

Update

var circle = svg.selectAll("circle")
    .data(data)
    .attr("cx", x)
    .attr("cy", y)
    .attr("r", 2.5);

When updating, you might ignore enter and exit.

Update

You see, the data method already does all the update work.

Existing elements, for which there were no new data.

Exit

var circle = svg.selectAll("circle")
    .data(data);

circle.exit().remove();

Typically you just call selection.remove on exit.

You can also create an exit transition, so that elements animate before removal.

Exit

Entering nodes are added to update on append.

Enter + Update

OK, one more special feature of the append method on enter selections. This makes it easier for you to operate on entering and updating elements simultaneously, without needing to reselect after computing the data join. This reduces code duplication.

Key Function

You can control the join; by default, the join is by index.

You can ignore key functions if you are creating static visualizations.

You usually need a key function only if you are doing transitions and want to maintain object constancy.

// A scatterplot, perhaps?
var data = [
  {name: "Alice", x: 10.0, y: 9.14},
  {name:   "Bob", x:  8.0, y: 8.14},
  {name: "Carol", x: 13.0, y: 8.74},
  {name:  "Dave", x:  9.0, y: 8.77},
  {name: "Edith", x: 11.0, y: 9.26}
];

If needed, data should have a unique key for joining.

Key Function

function key(d) { return d.name; }

var circle = svg.selectAll("circle")
    .data(data, key)
    .attr("cx", x)
    .attr("cy", y)
    .attr("r", 2.5);

The key function returns a unique string for each datum.

Key Function

D3 provides several convenience routines using XMLHttpRequest.

Loading data isn’t core feature of D3 per se, but since it’s commonly needed, there are a few built-in convenience methods.

Loading Data

Comma-Separated Values: d3.csv

Loading CSV

symbol,date,price
S&P 500,Jan 2000,1394.46
S&P 500,Feb 2000,1366.42
S&P 500,Mar 2000,1498.58
S&P 500,Apr 2000,1452.43
S&P 500,May 2000,1420.6
S&P 500,Jun 2000,1454.6
S&P 500,Jul 2000,1430.83

Loading CSV

var format = d3.time.format("%b %Y");

d3.csv("stocks.csv", function(stocks) {
  stocks.forEach(function(d) {
    d.price = +d.price;
    d.date = format.parse(d.date);
  });
});

CSV is untyped, so coercion from strings is required.

The array.forEach method is a built-in JavaScript method to iterate over all elements in an array (here rows in the loaded CSV file).

Loading CSV

Loading CSV

Loading JSON

JavaScript Object Notation: d3.json

Use JSON rather than JSONP, if you can.

JSONP is insecure (and as often practiced, synchronous). For loading cross-domain data, use the Access-Control-Allow-Origin: * header instead.

[{"symbol": "S&P 500", "date": "Jan 2000", "price": 1394.46},
 {"symbol": "S&P 500", "date": "Feb 2000", "price": 1366.42},
 {"symbol": "S&P 500", "date": "Mar 2000", "price": 1498.58},
 {"symbol": "S&P 500", "date": "Apr 2000", "price": 1452.43},
 {"symbol": "S&P 500", "date": "May 2000", "price": 1420.6},
 {"symbol": "S&P 500", "date": "Jun 2000", "price": 1454.6},
 {"symbol": "S&P 500", "date": "Jul 2000", "price": 1430.83}…

Loading JSON

var format = d3.time.format("%b %Y");

d3.json("stocks.json", function(stocks) {
  stocks.forEach(function(d) {
    d.date = format.parse(d.date);
  });
});

JSON is typed, but you must still parse dates.

Another option is to represent dates as UNIX epoch milliseconds or ISO 8601 strings, in which case you can use the Date constructor rather than a time format.

Loading JSON

Code that depends on data must be invoked via callback.

Data is Asynchronous

D3 doesn’t provide any synchronous methods for loading data.

Loading data asynchronously should give a better experience for your users, since the browser won’t stall while data is loading.

Data is rarely in the exact format needed for visualization.

Data is Messy

This doesn’t scratch the surface of the data cleaning problem.

For that, see projects such as Google Refine and Stanford’s Data Wrangler.

JavaScript has a number of useful built-in array methods.

Array.{ filtermapsort, …}

Deferring data transformations to the client often makes it easier for you to prototype visualizations rapidly; you can change the data on-the-fly rather than needing to re-run your data pipeline.

On the other hand, when you want to share your visualization with the world, it’s a good idea to optimize your dataset for performance.

D3 also has a variety of data-transform methods; explore the  API.

D3.{ nest, keys, values, …}

SCALES

Data ↦ Attributes

We use the data join to maintain the mapping from data to elements, but what about the mapping from data to attributes? 

We need to compute attributes from data to generate visual encodings (position, color, etc.). 

Visualization requires visual encoding: mapping data to elements.

Scales help with this.

SCALES

Domain ↦ Range

Some scales can also go the other way and compute an inverse mapping from range to domain (the scale.invert method) 

This is useful for interaction.

Scales are functions that map from data-space to visual-space.

function x(d) {
  return d * 42 + "px";
}

Scales are convenient but optional; you can roll your own.

The function x, here, is a linear scale. But it’s a pain to implement scales this way because you end up hard-coding the scale factor (e.g., 42).

SCALES

Quantitative SCALES

Map a continuous (numeric) domain to a continuous range.

Quantitative SCALES

var x = d3.scale.linear()
    .domain([12, 24])
    .range([0, 720]);

x(16); // 240

A linear scale simply translates and scales.

The domain of a scale is the expected data values (here from 12 to 24), while the range is the desired output values (0 is the left side of the chart, and 720 is the right side of the chart). Thus, this scale implements a position encoding.

Quantitative SCALES

var x = d3.scale.sqrt()
    .domain([12, 24])
    .range([0, 720]);

x(16); // 268.9056992603583

A sqrt (or pow) scale applies an exponential transform.

Sometimes you want to transform the data as part of the encoding. For example, you might use a square-root scale when computing the radius of a circle, so that the area is proportional to the associated data value.

Quantitative SCALES

var x = d3.scale.log()
    .domain([12, 24])
    .range([0, 720]);

x(16); // 298.82699948076737

A log scale applies a logarithmic transform.

Be careful that your log scale’s domain never crosses zero (which is at infinity)!

Domains & Ranges

Typically, domains are derived from data while ranges are constant.

var x = d3.scale.linear()
    .domain([0, d3.max(numbers)])
    .range([0, 720]);

Use d3.min and d3.max to compute the domain.

Domains & Ranges

var x = d3.scale.log()
    .domain(d3.extent(numbers))
    .range([0, 720]);

Use d3.extent to compute the min and max simultaneously.

Domains & Ranges

function value(d) { return d.value; }

var x = d3.scale.log()
    .domain(d3.extent(objects, value))
    .range([0, 720]);

Use an accessor function to derive a numeric value for objects.

Domains & Ranges

If you prefer, you can use array.map instead of an accessor function.

Interpolators

You can control the join; by default, the join is by index.

D3 has a powerful set of interpolators that are used by scales and transitions. It’s good to understand how interpolators work. Occasionally you might also find a reason to use an interpolator directly, or to write your own custom interpolator.

var x = d3.scale.linear()
    .domain([12, 24])
    .range(["steelblue", "brown"]);

x(16); // #666586

Colors are detected automatically for RGB interpolation.

D3 understands CSS2 colors (such as "#FFF" and "rgb(255,0,0)"). D3 might support perceptual color spaces in the future, namely CIE L*a*b*.

Interpolators

var x = d3.scale.linear()
    .domain([12, 24])
    .range(["0px", "720px"]);

x(16); // 240px

String interpolation matches embedded numbers; quite flexible.

Generic string interpolation can be used for CSS positions and sizes (which unlike CSS require units, such as "px" or "em"), for SVG path data, and other applications.

Interpolators

var x = d3.scale.linear()
    .domain([12, 24])
    .range(["steelblue", "brown"])
    .interpolate(d3.interpolateHsl);

x(16); // #3cb05f

Interpolators can be set explicitly, if desired.

Use HSL interpolation judiciously; rainbow color scales (hue interpolation) are a generally-accepted bad practice.

Interpolators

You can even interpolate objects!

Interpolators

Mousemove to see this demo.

This slide is contrived, but object interpolation is often used for transitions of complex data objects, such as donut charts or sunburst layouts.

Diverging SCALES

Sometimes, you want a compound (“polylinear”) scale.

var x = d3.scale.linear()
    .domain([-10, 0, 100])
    .range(["red", "white", "green"]);

x(-5); // #ff8080
x(50); // #80c080

The domain and range can have more than two values!

Diverging SCALES

Ordinal SCALES

Map a discrete domain to a discrete range.

var x = d3.scale.ordinal()
    .domain(["A", "B", "C", "D"])
    .range([0, 10, 20, 30]);

x("B"); // 10

An ordinal scale is essentially an explicit mapping.

You wouldn’t normally use an ordinal scale this way, but I’m including it as the most direct example of what an ordinal scale does. The first element in the domain is mapped to the first element in the range, and so on.

Ordinal SCALES

var x = d3.scale.category20()
    .domain(["A", "B", "C", "D"]);

x("B"); // #aec7e8

Ordinal scales are often used to assign categorical colors.

Ordinal SCALES

var x = d3.scale.category20()
    .domain(["A", "B", "C", "D"]);

x("E"); // #2ca02c
x("E"); // #2ca02c
x.domain(); // A, B, C, D, E

Unknown values are implicitly added to the domain.

You often don’t need to assign a domain explicitly with a categorical color scale; you can just start passing data to the scale and it will do the right thing. However, if you want a deterministic mapping (for example, the same colors across datasets or pages), then you’ll want to define the domain explicitly; otherwise it is order-dependent.

Ordinal SCALES

A handful of color scales are built-in; see also ColorBrewer.

Ordinal SCALES

var x = d3.scale.ordinal()
    .domain(["A", "B", "C", "D"])
    .rangePoints([0, 720]);

x("B"); // 240

Ordinal ranges can be derived from continuous ranges.

The rangePoints method might be used with an ordinal scatterplot.

Ordinal SCALES

var x = d3.scale.ordinal()
    .domain(["A", "B", "C", "D"])
    .rangeRoundBands([0, 720], .2);

x("B"); // 206, bar position
x.rangeBand(); // 137, bar width

Ordinal ranges are particularly useful for bar charts.

Here the scale returns the position of the left-side of the bar, while the rangeBand method returns the bar width. The second argument to rangeBands (here, .2) is the amount of padding to reserve between bars.

The rangeRoundBands method is the same as rangeBands, except it rounds to whole pixels to avoid blurry anti-aliasing.

Ordinal SCALES

Axes

D3 provides convenient labeling for scales.

In earlier releases, you had to label the axes yourself!

The d3.svg.axis component makes things much easier.

Axes

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

Create an axis for a given scale, and configure as desired.

There are a variety of other properties you might want to configure on an axis, such as the number of ticks or the tick format.

Axes

svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

Render the axis by calling a <g> selection.

You can also call the axis on a transition to animate changes to the domain!

Axes

.axis path, .axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

Customize axis appearance via CSS.

The CSS snippet here is a good default appearance for axes, but you can customize it however you like. The next slide shows a ggplot2-inspired appearance.

Axes

Ticks

Quantitative scales can be queried for “human-readable” values.

var x = d3.scale.linear()
    .domain([12, 24])
    .range([0, 720]);

x.ticks(5); // [12, 14, 16, 18, 20, 22, 24]

The requested count is only a hint (for better or worse).

Ticks

Ticks

Because the origin is in the top-left rather than bottom-left, you often see y-scales with an inverted range (e.g., [height, 0]).

Absolute positioning; the origin (0, 0) is the top-left corner!

SVG Coordinates

Use transforms to define a new origin.

SVG Coordinates

The "transform" attribute on <g> elements lets you define a new coordinate system. A translate lets you shift the origin based on margins; this approach is convenient because you isolate the margin definition to a single place in your code.

var svg = d3.select("body").append("svg")
    .attr("width", outerWidth)
    .attr("height", outerHeight);

var g = svg.append("g")
    .attr("transform", "translate("
      + marginLeft + ","
      + marginTop + ")");

Use margins for decorative elements, such as axes.

SVG Coordinates

SVG Basic Shapes

SVG Basic Shapes

<rect
    x="0"
    y="0"
    width="0"
    height="0"
    rx="0"
    ry="0">

Rect

Note that position and size must be defined as attributes in SVG, rather than styles. Colors and opacity should be specified as CSS, however.

SVG Basic Shapes

<circle
    cx="0"
    cy="0"
    r="0">

Circle

Don’t forget the r attribute, or your circles will be invisible!

SVG Basic Shapes

<line
    x1="0"
    y1="0"
    x2="0"
    y2="0">

Line

Mousemove?

SVG Basic Shapes

<text
    x="0"
    y="0"
    dx="0"
    dy="0"
    text-anchor="start">

Text

SVG is designed to be agnostic about text direction (left-to-right vs. right-to-left), so the text-anchor attribute can have the values "start", "middle" and "end".

<text dy="0">bottom</text>
<text dy=".35em">middle</text>
<text dy=".71em">top</text>

Vertical alignment of text is slightly awkward.

SVG Basic Shapes

SVG Path

<path d="M152.64962091501462,320.5600780855698L133.88913955606318,325.4363177123538L134.96890954443046,330.37917634921996L131.19348249532786,331.158393614812L98.56681109628815,335.53933807857004L91.14450799488135,333.79662025279L72.1880101321918…"

Paths require another mini-language!

It’s occasionally useful to generate path strings by hand, but since this is cumbersome, D3 provides ways to construct common path types from data.

SVG Path

Path Generators

Configurable functions for generating paths from data.

Define a path in terms of x and y.

var x = d3.scale.linear(),
    y = d3.scale.linear();

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

Compose scales with data accessors to define position.

svg.append("path")
    .datum(objects)
    .attr("class", "line")
    .attr("d", line);

Pass data to the line generator directly, or via selection.attr.

The datum operator lets you bind data to elements without computing a data-join; in this case, we’re assigning a single data point to a single element. The confusing part is that this single data point is actually an array of objects—since we’re using a single path element to visualize an array of data points. So occasionally the concept of mapping data to elements isn’t exactly one-to-one.

Define a path in terms of xy0 and y1.

var x = d3.scale.linear(),
    y = d3.scale.linear();

var area = d3.svg.area()
    .x(function(d) { return x(d.x); })
    .y0(height)
    .y1(function(d) { return y(d.y); });

For non-stacked area charts, y0 is constant.

For streamgraphs, use d3.layout.stack to compute the baseline.

Line and area generators support multiple interpolation modes.

Line Interpolators

Linear Interpolation

Mousemoooooove.

Step Interpolation

Step-before and step-after interpolation are handy for bar charts, and for visualizing step functions (values that change instantaneous­ly rather than gradually).

Basis Interpolation

Note that with basis interpolation, the line doesn’t always go through the control point. D3 also provides cardinal and cubic monotone interpolation; the latter is generally preferred to avoid misleading.

Similar to d3.svg.{area,line}, except in polar coordinates.

Radial Areas & Lines

See the examples included in the git repository.

A path generator for pie and donut charts, among other uses.

By default, takes as input an object with arc-related properties.

var myArc = {
  "innerRadius": 0,
  "outerRadius": 360,
  "startAngle": 0, // 12 o'clock
  "endAngle": 1.2 // radians
};

Override the accessors to set constant properties.

var arc = d3.svg.arc()
    .innerRadius(0)
    .outerRadius(360);

If you define the inner and outer radius as constants, you no longer need to specify them as properties on the input objects; so this arc generator could take as input {startAngle: 0, endAngle: 1.2}.

Use d3.layout.pie to compute start and end angles from data.

// construct a default pie layout
var pie = d3.layout.pie();

// derive data to feed to d3.svg.arc
var myArcs = pie(numbers);

The pie layout returns data objects with startAngle and endAngle properties that you can feed to d3.svg.arc.

Layouts

Layouts are Data

This abstract approach makes it easier to reuse layouts in interesting ways.

Such as combining the cluster layout with the bundle layout for hierarchical edge bundling.

Layouts are reusable algorithms that generate data, not display.

Even using layouts to render to Canvas rather than SVG.

Layouts are Varied

Each layout is different. Most are stateless, but not all.

Hierarchical Layouts

There are lots of ways to visualize hierarchical data!

Hierarchical Layouts

Hierarchical Layouts

Hierarchical Layouts

Hierarchical Layouts

The hierarchical layouts use a shared representation of data.

var parent = {"children": […]},
     child = {"value": …};

Hierarchical Layouts

You can use a different representation of data by changing the layout’s accessor functions, but most of the time it’s easiest to stick to the default data format.

Layouts are configurable functions.

var treemap = d3.layout.treemap()
    .padding(4)
    .size([width, height]);

Hierarchical Layouts

For example, here the padding controls the space reserved between a parent node in the treemap and its children. For a treemap, padding is necessary so that you can see the hierarchical structure; if you don’t use padding, you’ll want to use some other way of indicating the hierarchy, such as color.

The layout populates position properties on the nodes.

function x(d) { return d.x; }
function y(d) { return d.y; }
function dx(d) { return d.dx; }
function dy(d) { return d.dy; }

Hierarchical Layouts

This slide shows accessor functions for retrieving the layout’s computed properties; these accessor functions are used on the next slide to display the layout.

By accessing those properties, you can visualize the layout.

var parent = {"children": […]},
     child = {"value": …};
svg.selectAll(".cell")
    .data(treemap.nodes(root))
  .enter().append("rect")
    .attr("class", "cell")
    .attr("x", x)
    .attr("y", y)
    .attr("width", dx)
    .attr("height", dy);

Hierarchical Layouts

Force layouts are commonly used for visualizing networks, but they can also be used for fuzzy position encoding. For example, beeswarm plots are variants of scatterplots that use collision detection: rather than overplotting, coincident dots are pushed apart. There is a talk on force layouts that explains how these simulations work, and various interesting applications.

D3’s voronoi implementation is effectively a layout, but it lives in the d3.geom package. Voronoi diagrams are useful for scatterplots and other displays with small graphical elements: use the voronoi to find the closest point to the mouse. See also Tovi Grossman’s CHI 2005 paper on Bubble Cursors.

Mouseover to focus on rides to or from a single neighbor­hood.
The thickness of links be­tween neighborhoods encodes the relative frequency of rides between two neighborhoods: thicker links represent more frequent rides.
Links are directed: for exam­ple, while 2.2% of rides go from South of Market to Downtown, only 1.2% go in the opposite direction. Links are colored by the more fre­quent origin.

Reuse code through configurable functions.

Chart Components

D3 has a number of reusable components; Here didn’t cover all of them in the slides. There is an article outlining a lightweight convention for reusable components. You might find it useful when implementing your own visualizations.

The End

Kudos for reading all 140+ slides!

These slides were built with reveal.js and wrote on slides.com.

References

Many Thanks !

What is D3 ?

By seeskyblue