Skip to content

Instantly share code, notes, and snippets.

@timelyportfolio
Last active December 19, 2015 21:48
Show Gist options
  • Save timelyportfolio/6022406 to your computer and use it in GitHub Desktop.
Save timelyportfolio/6022406 to your computer and use it in GitHub Desktop.
#sankey of PIMCO All Asset All Authority holdings
#data source http://investments.pimco.com/ShareholderCommunications/External%20Documents/PIMCO%20Bond%20Stats.xls
require(rCharts)
#originally read the data from clipboard of Excel copy
#for those interested here is how to do it
#read.delim(file = "clipboard")
holdings = read.delim("http://timelyportfolio.github.io/rCharts_d3_sankey/holdings.txt", skip = 3, header = FALSE, stringsAsFactors = FALSE)
colnames(holdings) <- c("source","target","value")
#get rid of holdings with 0 weight or since copy/paste from Excel -
holdings <- holdings[-which(holdings$value == "-"),]
holdings$value <- as.numeric(holdings$value)
#now we finally have the data in the form we need
sankeyPlot <- rCharts$new()
sankeyPlot$setLib('http://timelyportfolio.github.io/rCharts_d3_sankey')
sankeyPlot$set(
data = holdings,
nodeWidth = 15,
nodePadding = 10,
layout = 32,
width = 750,
height = 500,
labelFormat = ".1%"
)
sankeyPlot
<!doctype HTML>
<meta charset = 'utf-8'>
<html>
<head>
<link rel='stylesheet' href="http://netdna.bootstrapcdn.com/bootswatch/2.3.1/cosmo/bootstrap.min.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" >
<link rel='stylesheet' href="http://twitter.github.io/bootstrap/assets/js/google-code-prettify/prettify.css">
<link rel='stylesheet' href="http://aozora.github.io/bootplus/assets/css/docs.css">
<link rel='stylesheet' href='http://timelyportfolio.github.io/rCharts_d3_sankey/css/sankey.css'>
<script src='http://d3js.org/d3.v3.min.js' type='text/javascript'></script>
<script src='http://timelyportfolio.github.io/rCharts_d3_sankey/js/sankey.js' type='text/javascript'></script>
<style>
.rChart {
display: block
margin: auto auto;
width: 100%;
height: 550px;
}
/*
body {
margin-top: 60px;
}
*/
</style>
</head>
<body>
<div class='container'>
<div class='row'>
<div class='span9'>
<div class="bs-docs-example">
<div id='chart1f7814dd24af' class='rChart nvd3Plot rCharts_d3_sankey'></div>
<br/>
<pre><code class='r'>#sankey of PIMCO All Asset All Authority holdings
#data source http://investments.pimco.com/ShareholderCommunications/External%20Documents/PIMCO%20Bond%20Stats.xls
require(rCharts)
#originally read the data from clipboard of Excel copy
#for those interested here is how to do it
#read.delim(file = &quot;clipboard&quot;)
holdings = read.delim(&quot;http://timelyportfolio.github.io/rCharts_d3_sankey/holdings.txt&quot;, skip = 3, header = FALSE, stringsAsFactors = FALSE)
colnames(holdings) &lt;- c(&quot;source&quot;,&quot;target&quot;,&quot;value&quot;)
#get rid of holdings with 0 weight or since copy/paste from Excel -
holdings &lt;- holdings[-which(holdings$value == &quot;-&quot;),]
holdings$value &lt;- as.numeric(holdings$value)
#now we finally have the data in the form we need
sankeyPlot &lt;- rCharts$new()
sankeyPlot$setLib('http://timelyportfolio.github.io/rCharts_d3_sankey')
sankeyPlot$set(
data = holdings,
nodeWidth = 15,
nodePadding = 10,
layout = 32,
width = 750,
height = 500,
labelFormat = &quot;.1%&quot;
)
sankeyPlot
</code></pre>
</div>
</div>
</div>
</div>
<!--Attribution:
Mike Bostock https://github.com/d3/d3-plugins/tree/master/sankey
Mike Bostock http://bost.ocks.org/mike/sankey/
-->
<script>
(function(){
var params = {
"dom": "chart1f7814dd24af",
"width": 750,
"height": 500,
"data": {
"source": [ "All Asset All Authority", "Short-Term Strategies:", "Short-Term Strategies:", "Short-Term Strategies:", "All Asset All Authority", "US Core and Long Maturity Bond Strategies:", "US Core and Long Maturity Bond Strategies:", "US Core and Long Maturity Bond Strategies:", "US Core and Long Maturity Bond Strategies:", "US Core and Long Maturity Bond Strategies:", "All Asset All Authority", "EM and Global Bond Strategies:", "EM and Global Bond Strategies:", "EM and Global Bond Strategies:", "EM and Global Bond Strategies:", "EM and Global Bond Strategies:", "EM and Global Bond Strategies:", "EM and Global Bond Strategies:", "All Asset All Authority", "Credit Strategies:", "Credit Strategies:", "Credit Strategies:", "Credit Strategies:", "Credit Strategies:", "Credit Strategies:", "All Asset All Authority", "Inflation Related Strategies:", "Inflation Related Strategies:", "Inflation Related Strategies:", "Inflation Related Strategies:", "Inflation Related Strategies:", "Inflation Related Strategies:", "All Asset All Authority", "US Equity Strategies:", "US Equity Strategies:", "US Equity Strategies:", "US Equity Strategies:", "US Equity Strategies:", "All Asset All Authority", "Global Equity Strategies:", "Global Equity Strategies:", "Global Equity Strategies:", "Global Equity Strategies:", "Global Equity Strategies:", "Global Equity Strategies:", "Global Equity Strategies:", "All Asset All Authority", "Alternative Strategies:", "Alternative Strategies:", "Alternative Strategies:", "Alternative Strategies:", "Alternative Strategies:", "Alternative Strategies:" ],
"target": [ "Short-Term Strategies:", "Low Duration Fund", "Short Term Fund", "Net Cash Equivalents", "US Core and Long Maturity Bond Strategies:", "Investment Grade Corporate Bond Fund", "Long Duration Total Return Fund ", "Long Term Credit Fund", "Long-Term US Government Fund", "Total Return Fund", "EM and Global Bond Strategies:", "Diversified Income Fund", "Emerging Local Bond Fund", "Emerging Markets Bond Fund", "Emerging Markets Corporate Bond Fund", "Emerging Markets Currency", "Foreign Bond Fund (Unhedged)", "Global Advantage Strategy Bond Fund", "Credit Strategies:", "Convertible Fund", "Floating Income Fund", "High Yield Fund", "High Yield Spectrum Fund", "Income Fund", "Senior Floating Rate Fund", "Inflation Related Strategies:", "CommoditiesPLUS? Strategy Fund", "CommodityRealReturn Strategy Fund?", "Global Advantage? Inflation-Linked Bond Exchange-Traded Fund", "Real Return Asset Fund", "Real Return Fund", "RealEstateRealReturn Strategy Fund", "US Equity Strategies:", "Fundamental IndexPLUS? AR Fund", "Small Cap StocksPLUS? AR Strategy Fund", "Small Company Fundamental IndexPLUS? AR Strategy Fund", "StocksPLUS? Fund", "StocksPLUS? Absolute Return Fund", "Global Equity Strategies:", "EM Fundamental IndexPLUS? AR Strategy Fund", "EqS Dividend Fund", "EqS Emerging Markets Fund", "EqS Pathfinder Fund", "International Fundamental IndexPLUS? AR Strategy Fund", "International StocksPLUS? AR Strategy Fund (U.S. Dollar Hedged)", "International StocksPLUS? AR Strategy Fund (Unhedged)", "Alternative Strategies:", "Credit Absolute Return Fund", "EqS Long/Short Fund", "Fundamental Advantage Absolute Return Strategy Fund", "StocksPLUS? Short Strategy Fund", "Unconstrained Bond Fund", "Worldwide Fundamental Advantage AR Strategy Fund" ],
"value": [ 0.017024, 0.0026674, 0.00012369, 0.014233, 0.14679, 0.030653, 0.02253, 0.011865, 0.01862, 0.06312, 0.23159, 0.043637, 0.054611, 0.036499, 0.0097153, 0.060992, 0.010786, 0.015353, 0.20672, 0.0048379, 0.030494, 0.061942, 0.03124, 0.05314, 0.025066, 0.041657, 0.031861, 0.0038519, 0.00050879, 0.0021003, 0.00033372, 0.0030014, 0.010194, 0.0011811, 0.0021201, 0.0062179, 0.00026106, 0.00041347, 0.09421, 0.045525, 0.00052989, 0.00072863, 0.011463, 0.034338, 0.00094173, 0.00068405, 0.25181, 0.0087691, 0.0029521, 0.039427, 0.12445, 0.051243, 0.024974 ]
},
"nodeWidth": 15,
"nodePadding": 10,
"layout": 32,
"labelFormat": ".1%",
"id": "chart1f7814dd24af"
};
params.units ? units = " " + params.units : units = "";
//hard code these now but eventually make available
var formatNumber = d3.format("0,.0f"), // zero decimal places
format = function(d) { return formatNumber(d) + units; },
color = d3.scale.category20();
if(params.labelFormat){
formatNumber = d3.format(".2%");
}
var svg = d3.select('#' + params.id).append("svg")
.attr("width", params.width)
.attr("height", params.height);
var sankey = d3.sankey()
.nodeWidth(params.nodeWidth)
.nodePadding(params.nodePadding)
.layout(params.layout)
.size([params.width,params.height]);
var path = sankey.link();
var data = params.data,
links = [],
nodes = [];
//get all source and target into nodes
//will reduce to unique in the next step
//also get links in object form
data.source.forEach(function (d, i) {
nodes.push({ "name": data.source[i] });
nodes.push({ "name": data.target[i] });
links.push({ "source": data.source[i], "target": data.target[i], "value": +data.value[i] });
});
//now get nodes based on links data
//thanks Mike Bostock https://groups.google.com/d/msg/d3-js/pl297cFtIQk/Eso4q_eBu1IJ
//this handy little function returns only the distinct / unique nodes
nodes = d3.keys(d3.nest()
.key(function (d) { return d.name; })
.map(nodes));
//it appears d3 with force layout wants a numeric source and target
//so loop through each link replacing the text with its index from node
links.forEach(function (d, i) {
links[i].source = nodes.indexOf(links[i].source);
links[i].target = nodes.indexOf(links[i].target);
});
//now loop through each nodes to make nodes an array of objects rather than an array of strings
nodes.forEach(function (d, i) {
nodes[i] = { "name": d };
});
sankey
.nodes(nodes)
.links(links)
.layout(params.layout);
var link = svg.append("g").selectAll(".link")
.data(links)
.enter().append("path")
.attr("class", "link")
.attr("d", path)
.style("stroke-width", function (d) { return Math.max(1, d.dy); })
.sort(function (a, b) { return b.dy - a.dy; });
link.append("title")
.text(function (d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); });
var node = svg.append("g").selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; })
.call(d3.behavior.drag()
.origin(function (d) { return d; })
.on("dragstart", function () { this.parentNode.appendChild(this); })
.on("drag", dragmove));
node.append("rect")
.attr("height", function (d) { return d.dy; })
.attr("width", sankey.nodeWidth())
.style("fill", function (d) { return d.color = color(d.name.replace(/ .*/, "")); })
.style("stroke", function (d) { return d3.rgb(d.color).darker(2); })
.append("title")
.text(function (d) { return d.name + "\n" + format(d.value); });
node.append("text")
.attr("x", -6)
.attr("y", function (d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function (d) { return d.name; })
.filter(function (d) { return d.x < params.width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start");
// the function for moving the nodes
function dragmove(d) {
d3.select(this).attr("transform",
"translate(" + (
d.x = Math.max(0, Math.min(params.width - d.dx, d3.event.x))
) + "," + (
d.y = Math.max(0, Math.min(params.height - d.dy, d3.event.y))
) + ")");
sankey.relayout();
link.attr("d", path);
}
})();
</script>
</body>
<!-- Google Prettify -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/prettify/188.0.0/prettify.js"></script>
<script
src='https://google-code-prettify.googlecode.com/svn-history/r232/trunk/src/lang-r.js'>
</script>
<script>
var pres = document.getElementsByTagName("pre");
for (var i=0; i < pres.length; ++i) {
pres[i].className = "prettyprint linenums";
}
prettyPrint();
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment