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.
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
)
))
)
)
<!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>