block by timelyportfolio ac9610255813243b3271334086eff2a9

d3-sankey on Titanic

Full Screen

This example courtesy of Displayr who have generously offered to sponsor a series of independently authored posts about interactive visualization with R and JavaScript. Thank you so much Displayr for this opportunity.


Code in R

Below is the R source code for creating this visualization. You might notice that much of this is actually JavaScript. To see the JavaScript, please inspect index.html.

library(d3r)
library(dplyr)
library(htmltools)

titan_ndlnk <- d3_table(Titanic, vars=c("Class","Sex","Survived"))
titan_ndlnk <- jsonlite::toJSON(
  titan_ndlnk,
  dataframe = "rows"
)

browsable(
  tagList(
    d3_dep_v4(offline=FALSE),
    tags$head(tags$script(src="https://unpkg.com/d3-sankey")),
    tag("svg", list(id="tree", height=600, width=800)),
    tags$script(HTML(
sprintf(
"
var titanic = %s;
var sankey = d3.sankey()
  .extent([[1,1],[750,400]])(titanic);

var color = d3.scaleOrdinal(d3.schemeCategory10);

var tree_g = d3.select('#tree')
  .append('g')
  .attr('transform', 'translate(60,20)');

var links = tree_g.selectAll('.link')
  .data(sankey.links);

links = links.merge(
  links.enter()
    .append('path')
    .classed('link', true)
)

links
  .attr('d', d3.sankeyLinkHorizontal())
  .style('fill', 'none')
  .style('stroke', function(d) {
    return color(d.target.name);
  })
  .style('stroke-opacity', 0.5)
  .attr('stroke-width', function(d) {
    return Math.max(1, d.width);
  });

var nodes = tree_g.selectAll('.node')
  .data(sankey.nodes);

nodes = nodes.merge(
  nodes
    .enter()
    .append('g')
    .classed('node', true)
)

nodes
  .append('rect')
  .attr('x', function(d) {
    return d.x0;
  })
  .attr('y', function(d) {
    return d.y0;
  })
  .attr('height', function(d) {
    return d.y1 - d.y0;
  })
  .attr('width', function(d) {
    return d.x1 - d.x0;
  })
  .style('fill', function(d) {
    return color(d.name);
  })

nodes
  .append('text')
  .attr('x', function(d) { return d.x0 - 6; })
  .attr('y', function(d) { return (d.y1 + d.y0) / 2; })
  .attr('dy', '0.35em')
  .attr('text-anchor', 'end')
  .text(function(d) { return d.name; })

",
titan_ndlnk
)
    ))
  )
)

index.html


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="https://unpkg.com/d3@4.9.1"></script>
  <script src="https://unpkg.com/d3-sankey@0.7.1"></script>
</head>
<body style="background-color:white;">
<svg id="tree" height="600" width="800"></svg>
<script>
var titanic = {"nodes":[{"name":"1st","weight":325},{"name":"2nd","weight":285},{"name":"3rd","weight":706},{"name":"Crew","weight":885},{"name":"Male","weight":1731},{"name":"Female","weight":470},{"name":"No","weight":1490},{"name":"Yes","weight":711},{"name":"Titanic","weight":2201}],"links":[{"source":0,"target":4,"value":180},{"source":1,"target":4,"value":179},{"source":2,"target":4,"value":510},{"source":3,"target":4,"value":862},{"source":0,"target":5,"value":145},{"source":1,"target":5,"value":106},{"source":2,"target":5,"value":196},{"source":3,"target":5,"value":23},{"source":4,"target":6,"value":1364},{"source":5,"target":6,"value":126},{"source":4,"target":7,"value":367},{"source":5,"target":7,"value":344},{"source":8,"target":0,"value":325},{"source":8,"target":1,"value":285},{"source":8,"target":2,"value":706},{"source":8,"target":3,"value":885}]};
var sankey = d3.sankey()
  .extent([[1,1],[750,400]])(titanic);

var color = d3.scaleOrdinal(d3.schemeCategory10);

var tree_g = d3.select('#tree')
  .append('g')
  .attr('transform', 'translate(60,20)');

var links = tree_g.selectAll('.link')
  .data(sankey.links);

links = links.merge(
  links.enter()
    .append('path')
    .classed('link', true)
)

links
  .attr('d', d3.sankeyLinkHorizontal())
  .style('fill', 'none')
  .style('stroke', function(d) {
    return color(d.target.name);
  })
  .style('stroke-opacity', 0.5)
  .attr('stroke-width', function(d) {
    return Math.max(1, d.width);
  });

var nodes = tree_g.selectAll('.node')
  .data(sankey.nodes);

nodes = nodes.merge(
  nodes
    .enter()
    .append('g')
    .classed('node', true)
)

nodes
  .append('rect')
  .attr('x', function(d) {
    return d.x0;
  })
  .attr('y', function(d) {
    return d.y0;
  })
  .attr('height', function(d) {
    return d.y1 - d.y0;
  })
  .attr('width', function(d) {
    return d.x1 - d.x0;
  })
  .style('fill', function(d) {
    return color(d.name);
  })

nodes
  .append('text')
  .attr('x', function(d) { return d.x0 - 6; })
  .attr('y', function(d) { return (d.y1 + d.y0) / 2; })
  .attr('dy', '0.35em')
  .attr('text-anchor', 'end')
  .text(function(d) { return d.name; })

</script>
</body>
</html>