Skip to content

Instantly share code, notes, and snippets.

@pdavidsonFIA
Last active May 12, 2022 13:41
Show Gist options
  • Save pdavidsonFIA/ce3a1f8ab87c613912ed7a6dac68f539 to your computer and use it in GitHub Desktop.
Save pdavidsonFIA/ce3a1f8ab87c613912ed7a6dac68f539 to your computer and use it in GitHub Desktop.
org chart using d3.js force network
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
text {
font-family: sans-serif;
font-size: 10px;
}
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
d3.json("org_chart.json", function(error, graph) {
if (error) throw error;
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("g")
.data(graph.nodes)
.enter().append("g")
var circles = node.append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); });
// Create a drag handler and append it to the node object instead
var drag_handler = d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
drag_handler(node);
var lables = node.append("text")
.text(function(d) {
return d.id;
})
.attr('x', 6)
.attr('y', 3);
node.append("title")
.text(function(d) { return d.id; });
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
}
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
</script>
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Generate json data for org chart"
]
},
{
"cell_type": "code",
"execution_count": 86,
"metadata": {},
"outputs": [],
"source": [
"people = ['Peter', 'Dario', 'Jean', 'Oleg', 'Bilal', 'Amine', 'JB']\n",
"bau = ['Reserving', 'SolvencyII', 'ProductSTA', 'Reinsurance', 'ActuarialSystems']\n",
"projects = ['IFRS17', 'Anaplan', 'ProjectA']\n",
"cross_function = ['Planning', 'PortfolioMonitoring', 'RiskMgmt', 'ORSA', 'Data', 'BusinessCases']"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'id': 'Peter', 'group': 1},\n",
" {'id': 'Dario', 'group': 1},\n",
" {'id': 'Jean', 'group': 1},\n",
" {'id': 'Oleg', 'group': 1},\n",
" {'id': 'Bilal', 'group': 1},\n",
" {'id': 'Amine', 'group': 1},\n",
" {'id': 'JB', 'group': 1},\n",
" {'id': 'Reserving', 'group': 2},\n",
" {'id': 'SolvencyII', 'group': 2},\n",
" {'id': 'ProductSTA', 'group': 2},\n",
" {'id': 'Reinsurance', 'group': 2},\n",
" {'id': 'ActuarialSystems', 'group': 2},\n",
" {'id': 'IFRS17', 'group': 3},\n",
" {'id': 'Anaplan', 'group': 3},\n",
" {'id': 'ProjectA', 'group': 3},\n",
" {'id': 'Planning', 'group': 4},\n",
" {'id': 'PortfolioMonitoring', 'group': 4},\n",
" {'id': 'RiskMgmt', 'group': 4},\n",
" {'id': 'ORSA', 'group': 4},\n",
" {'id': 'Data', 'group': 4},\n",
" {'id': 'BusinessCases', 'group': 4}]"
]
},
"execution_count": 87,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nodes = [{'id': x, 'group': 1} for x in people] + \\\n",
" [{'id': x, 'group': 2} for x in bau] + \\\n",
" [{'id': x, 'group': 3} for x in projects] + \\\n",
" [{'id': x, 'group': 4} for x in cross_function] \n",
"nodes"
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[{'source': 'Dario', 'target': 'Peter', 'value': 2.0},\n",
" {'source': 'Jean', 'target': 'Peter', 'value': 2.0},\n",
" {'source': 'Oleg', 'target': 'Peter', 'value': 2.0},\n",
" {'source': 'Bilal', 'target': 'Peter', 'value': 2.0},\n",
" {'source': 'Amine', 'target': 'Dario', 'value': 2.0},\n",
" {'source': 'JB', 'target': 'Bilal', 'value': 2.0},\n",
" {'source': 'Reinsurance', 'target': 'Peter', 'value': 3.0},\n",
" {'source': 'Planning', 'target': 'Peter', 'value': 4.0},\n",
" {'source': 'BusinessCases', 'target': 'Peter', 'value': 3.0},\n",
" {'source': 'Reserving', 'target': 'Dario', 'value': 3.0},\n",
" {'source': 'Reinsurance', 'target': 'Dario', 'value': 2.0},\n",
" {'source': 'RiskMgmt', 'target': 'Dario', 'value': 3.0},\n",
" {'source': 'PortfolioMonitoring', 'target': 'Dario', 'value': 2.0},\n",
" {'source': 'ProjectA', 'target': 'Jean', 'value': 5.0},\n",
" {'source': 'ProductSTA', 'target': 'Jean', 'value': 5.0},\n",
" {'source': 'ProductSTA', 'target': 'Oleg', 'value': 1.0},\n",
" {'source': 'ActuarialSystems', 'target': 'Oleg', 'value': 3.0},\n",
" {'source': 'Anaplan', 'target': 'Oleg', 'value': 4.0},\n",
" {'source': 'Data', 'target': 'Oleg', 'value': 1.0},\n",
" {'source': 'ORSA', 'target': 'Oleg', 'value': 2.0},\n",
" {'source': 'IFRS17', 'target': 'Bilal', 'value': 6.0},\n",
" {'source': 'SolvencyII', 'target': 'Bilal', 'value': 2.0},\n",
" {'source': 'RiskMgmt', 'target': 'Bilal', 'value': 1.0},\n",
" {'source': 'Planning', 'target': 'Bilal', 'value': 1.0},\n",
" {'source': 'ORSA', 'target': 'Bilal', 'value': 2.0},\n",
" {'source': 'Reserving', 'target': 'Amine', 'value': 6.0},\n",
" {'source': 'PortfolioMonitoring', 'target': 'Amine', 'value': 4.0},\n",
" {'source': 'SolvencyII', 'target': 'JB', 'value': 5.0},\n",
" {'source': 'ActuarialSystems', 'target': 'JB', 'value': 5.0},\n",
" {'source': 'Data', 'target': 'Peter', 'value': 0.2},\n",
" {'source': 'Data', 'target': 'Dario', 'value': 0.2},\n",
" {'source': 'Data', 'target': 'Jean', 'value': 0.2},\n",
" {'source': 'Data', 'target': 'Oleg', 'value': 0.2},\n",
" {'source': 'Data', 'target': 'Bilal', 'value': 0.2},\n",
" {'source': 'Data', 'target': 'Amine', 'value': 0.2},\n",
" {'source': 'Data', 'target': 'JB', 'value': 0.2}]"
]
},
"execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Stuff people work on with weights:\n",
"work = {'Peter': {'topics': ['Reinsurance', 'Planning', 'BusinessCases'], 'weights': [0.3, 0.4, 0.3]},\n",
" 'Dario': {'topics': ['Reserving', 'Reinsurance', 'RiskMgmt', 'PortfolioMonitoring'], 'weights': [0.3, 0.2, 0.3, 0.2]},\n",
" 'Jean': {'topics': ['ProjectA', 'ProductSTA'], 'weights': [0.5, 0.5]},\n",
" 'Oleg': {'topics': ['ProductSTA', 'ActuarialSystems', 'Anaplan', 'Data', 'ORSA'], 'weights': [0.1, 0.3, 0.4, 0.1,0.2]},\n",
" 'Bilal': {'topics': ['IFRS17', 'SolvencyII', 'RiskMgmt', 'Planning', 'ORSA'], 'weights': [0.6, 0.2, 0.1, 0.1,0.2]},\n",
" 'Amine': {'topics': ['Reserving', 'PortfolioMonitoring'], 'weights': [0.6, 0.4]},\n",
" 'JB': {'topics': ['SolvencyII', 'ActuarialSystems'], 'weights': [0.5,0.5]}}\n",
"\n",
"reporting_lines = {'Dario':'Peter', 'Jean':'Peter', 'Oleg':'Peter', 'Bilal':'Peter', 'Amine':'Dario', 'JB':'Bilal'}\n",
"\n",
"links = []\n",
"\n",
"links += [{'source': k, 'target': v, 'value': 2.} for k, v in reporting_lines.items()]\n",
"links += [{'source': v['topics'][i], \n",
" 'target': p, \n",
" 'value': v['weights'][i]*10} \n",
" for p, v in work.items() for i in range(len(v['topics']))]\n",
"# Everybody works with data:\n",
"links += [{'source':'Data', 'target': p, 'value': 0.2} for p in people]\n",
"\n",
"links"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"json_prep = {\"links\":links, \"nodes\":nodes}\n",
"json_dump = json.dumps(json_prep, indent=1, sort_keys=True)\n",
"filename_out = 'org_chart.json'\n",
"json_out = open(filename_out,'w')\n",
"json_out.write(json_dump)\n",
"json_out.close()\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"state": {},
"version_major": 2,
"version_minor": 0
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}
{
"links": [
{
"source": "Dario",
"target": "Peter",
"value": 2.0
},
{
"source": "Jean",
"target": "Peter",
"value": 2.0
},
{
"source": "Oleg",
"target": "Peter",
"value": 2.0
},
{
"source": "Bilal",
"target": "Peter",
"value": 2.0
},
{
"source": "Amine",
"target": "Dario",
"value": 2.0
},
{
"source": "JB",
"target": "Bilal",
"value": 2.0
},
{
"source": "Reinsurance",
"target": "Peter",
"value": 3.0
},
{
"source": "Planning",
"target": "Peter",
"value": 4.0
},
{
"source": "BusinessCases",
"target": "Peter",
"value": 3.0
},
{
"source": "Reserving",
"target": "Dario",
"value": 3.0
},
{
"source": "Reinsurance",
"target": "Dario",
"value": 2.0
},
{
"source": "RiskMgmt",
"target": "Dario",
"value": 3.0
},
{
"source": "PortfolioMonitoring",
"target": "Dario",
"value": 2.0
},
{
"source": "ProjectA",
"target": "Jean",
"value": 5.0
},
{
"source": "ProductSTA",
"target": "Jean",
"value": 5.0
},
{
"source": "ProductSTA",
"target": "Oleg",
"value": 1.0
},
{
"source": "ActuarialSystems",
"target": "Oleg",
"value": 3.0
},
{
"source": "Anaplan",
"target": "Oleg",
"value": 4.0
},
{
"source": "Data",
"target": "Oleg",
"value": 1.0
},
{
"source": "ORSA",
"target": "Oleg",
"value": 2.0
},
{
"source": "IFRS17",
"target": "Bilal",
"value": 6.0
},
{
"source": "SolvencyII",
"target": "Bilal",
"value": 2.0
},
{
"source": "RiskMgmt",
"target": "Bilal",
"value": 1.0
},
{
"source": "Planning",
"target": "Bilal",
"value": 1.0
},
{
"source": "ORSA",
"target": "Bilal",
"value": 2.0
},
{
"source": "Reserving",
"target": "Amine",
"value": 6.0
},
{
"source": "PortfolioMonitoring",
"target": "Amine",
"value": 4.0
},
{
"source": "SolvencyII",
"target": "JB",
"value": 5.0
},
{
"source": "ActuarialSystems",
"target": "JB",
"value": 5.0
},
{
"source": "Data",
"target": "Peter",
"value": 0.2
},
{
"source": "Data",
"target": "Dario",
"value": 0.2
},
{
"source": "Data",
"target": "Jean",
"value": 0.2
},
{
"source": "Data",
"target": "Oleg",
"value": 0.2
},
{
"source": "Data",
"target": "Bilal",
"value": 0.2
},
{
"source": "Data",
"target": "Amine",
"value": 0.2
},
{
"source": "Data",
"target": "JB",
"value": 0.2
}
],
"nodes": [
{
"group": 1,
"id": "Peter"
},
{
"group": 1,
"id": "Dario"
},
{
"group": 1,
"id": "Jean"
},
{
"group": 1,
"id": "Oleg"
},
{
"group": 1,
"id": "Bilal"
},
{
"group": 1,
"id": "Amine"
},
{
"group": 1,
"id": "JB"
},
{
"group": 2,
"id": "Reserving"
},
{
"group": 2,
"id": "SolvencyII"
},
{
"group": 2,
"id": "ProductSTA"
},
{
"group": 2,
"id": "Reinsurance"
},
{
"group": 2,
"id": "ActuarialSystems"
},
{
"group": 3,
"id": "IFRS17"
},
{
"group": 3,
"id": "Anaplan"
},
{
"group": 3,
"id": "ProjectA"
},
{
"group": 4,
"id": "Planning"
},
{
"group": 4,
"id": "PortfolioMonitoring"
},
{
"group": 4,
"id": "RiskMgmt"
},
{
"group": 4,
"id": "ORSA"
},
{
"group": 4,
"id": "Data"
},
{
"group": 4,
"id": "BusinessCases"
}
]
}
body {
font-family: 'Source Sans Pro', sans-serif;
font-weight: 300;
}
b {
font-weight: 900;
}
.outline {
fill: none;
stroke: #888888;
stroke-width: 1px;
}
#tooltip {
font-size: 10pt;
font-weight: 900;
fill: #000000;
stroke: #ffffff;
stroke-width: 0.25px;
}
.node {
stroke: #ffffff;
stroke-weight: 1px;
}
.link {
fill: none;
stroke: #888888;
stroke-weight: 1px;
stroke-opacity: 0.5;
}
.highlight {
stroke: red;
stroke-weight: 4px;
stroke-opacity: 1.0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment