Skip to content

Instantly share code, notes, and snippets.

@jalapic
Last active November 8, 2015 23:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jalapic/2b0b96728f363d9fb7f1 to your computer and use it in GitHub Desktop.
Save jalapic/2b0b96728f363d9fb7f1 to your computer and use it in GitHub Desktop.
Networks - Graphs 2

Graph Example 2 for How to Create Effective Network Data Visualization

Changing the network topology interactively. Nodes or edges can be removed by double-clicking on them. This filters the corresponding entries in the node and edge arrays, re-applies them to the force layout, and exits the necessary elements.

This requires setting key values for the selection when the data-binding is done.

It also introduces SVG:g elements for edges, so that a much thicker, fully-transparent under-edge can be created not only to increase the interaction surface for the edge but also to provide visual feedback (the blue highlighting) when a user mouses over the edge.

For exploratory and explanatory network data visualization, interactivity like this can be very effective to demonstrate the importance or unimportance of certain nodes or edges. Allowing for changes to network topology by the user also promote network literacy, which is critical for organizations that intend to use network data visualization effectively.

source target weight
1 3 5
1 8 3
1 9 3
1 12 3
1 15 2
1 23 3
1 26 2
1 37 2
1 46 2
2 1 1
2 4 2
2 5 1
2 6 3
2 7 5
2 8 4
2 10 1
2 11 5
2 12 1
2 13 4
2 14 4
2 16 2
2 18 3
2 19 2
2 20 5
2 21 1
2 22 3
2 25 3
2 26 1
2 27 4
2 28 4
2 29 5
2 31 2
2 33 2
2 34 3
2 35 5
2 37 1
2 38 4
2 41 3
3 1 4
3 4 1
3 8 1
3 9 4
3 12 4
3 22 1
3 31 1
3 32 4
3 33 2
3 37 1
3 46 4
4 8 3
4 11 2
4 20 2
4 32 3
4 33 3
4 40 5
5 2 1
5 6 5
5 7 1
5 13 1
5 14 2
5 17 1
5 18 1
5 19 5
5 20 3
5 21 2
5 23 3
5 25 3
5 26 5
5 27 2
5 28 1
5 29 3
5 34 1
5 36 3
5 38 1
5 39 4
5 44 3
5 45 5
6 2 1
6 5 3
6 7 1
6 11 1
6 13 1
6 14 1
6 17 3
6 19 4
6 20 2
6 21 3
6 23 3
6 25 5
6 26 5
6 27 1
6 28 5
6 29 1
6 35 1
6 36 5
6 38 1
6 39 5
6 44 5
6 45 4
7 2 5
7 8 3
7 11 3
7 13 3
7 14 5
7 19 2
7 20 4
7 23 2
7 26 2
7 27 2
7 28 2
7 29 4
7 34 4
7 35 5
7 38 2
7 45 2
8 1 4
8 2 3
8 3 2
8 4 4
8 7 3
8 9 3
8 10 3
8 11 1
8 12 4
8 15 2
8 16 2
8 18 1
8 19 1
8 20 2
8 22 4
8 29 1
8 31 5
8 32 4
8 33 5
8 34 3
8 37 2
8 38 2
8 40 2
8 41 3
8 42 1
8 43 1
8 45 1
8 46 1
9 1 3
9 3 2
9 4 1
9 8 1
9 12 1
9 15 1
9 17 5
9 18 1
9 26 1
9 31 1
9 32 2
9 33 1
9 37 1
9 40 1
9 46 1
10 1 3
10 2 1
10 4 1
10 8 4
10 9 5
10 11 1
10 12 1
10 14 1
10 17 5
10 18 1
10 19 1
10 20 2
10 23 2
10 28 2
10 31 2
10 33 1
10 34 1
10 37 2
10 38 3
10 40 2
10 41 2
10 42 1
10 43 2
10 44 1
10 45 1
11 2 5
11 20 4
11 38 3
11 45 4
12 1 3
12 2 1
12 3 2
12 4 1
12 5 1
12 6 1
12 7 1
12 8 3
12 9 2
12 10 1
12 11 1
12 13 1
12 14 1
12 15 1
12 16 1
12 17 1
12 18 1
12 19 1
12 20 1
12 21 1
12 22 5
12 23 1
12 24 1
12 25 1
12 26 1
12 27 1
12 28 1
12 29 1
12 30 1
12 31 2
12 32 2
12 33 5
12 34 1
12 35 1
12 36 1
12 37 2
12 38 1
12 39 1
12 40 1
12 41 2
12 42 1
12 43 1
12 44 1
12 45 1
12 46 5
13 2 3
13 5 1
13 6 1
13 7 2
13 11 1
13 17 1
13 18 2
13 19 2
13 20 2
13 21 1
13 23 1
13 25 1
13 26 1
13 27 2
13 28 1
13 29 3
13 34 1
13 35 1
13 38 1
13 44 1
13 45 1
14 2 4
14 5 1
14 6 1
14 7 2
14 8 1
14 11 1
14 19 1
14 20 3
14 22 1
14 23 1
14 27 1
14 28 1
14 31 1
14 33 1
14 35 1
14 38 2
14 41 1
14 45 1
16 1 1
16 2 1
16 3 1
16 4 1
16 5 1
16 6 1
16 7 1
16 8 1
16 9 1
16 10 1
16 11 1
16 12 1
16 13 1
16 14 1
16 15 1
16 17 1
16 18 1
16 19 1
16 20 1
16 21 1
16 22 1
16 23 1
16 24 1
16 25 1
16 26 1
16 27 1
16 28 1
16 29 1
16 30 1
16 31 1
16 32 1
16 33 1
16 34 1
16 35 1
16 36 1
16 37 1
16 38 1
16 39 1
16 40 1
16 41 1
16 42 1
16 43 1
16 44 1
16 45 1
16 46 1
17 5 1
17 6 2
17 10 5
17 13 1
17 19 3
17 20 1
17 21 1
17 23 4
17 25 2
17 26 3
17 28 3
17 29 3
17 36 2
17 38 1
17 39 2
17 44 3
17 45 3
18 1 1
18 2 4
18 5 2
18 7 2
18 8 2
18 9 1
18 10 1
18 11 2
18 13 5
18 15 1
18 16 1
18 20 4
18 22 2
18 25 4
18 26 2
18 27 3
18 28 2
18 29 2
18 31 3
18 33 3
18 34 3
18 35 1
18 37 2
18 38 2
18 40 2
19 2 3
19 5 5
19 6 5
19 7 3
19 11 2
19 13 3
19 14 2
19 17 3
19 20 2
19 21 2
19 25 3
19 26 5
19 27 2
19 28 3
19 29 2
19 36 5
19 38 3
19 39 5
19 44 5
19 45 5
20 1 2
20 2 3
20 4 2
20 5 2
20 6 2
20 7 3
20 8 4
20 9 1
20 10 2
20 11 4
20 12 2
20 13 5
20 14 4
20 17 1
20 18 4
20 19 3
20 21 1
20 22 2
20 23 3
20 25 3
20 26 2
20 27 4
20 28 4
20 29 4
20 31 3
20 34 3
20 35 2
20 36 2
20 38 4
20 41 2
20 43 2
20 44 3
20 45 5
21 2 2
21 6 3
21 17 4
21 19 2
21 20 3
21 23 2
21 25 2
21 26 3
21 27 2
21 28 3
21 29 4
21 36 2
21 39 2
21 44 4
21 45 4
22 1 1
22 2 2
22 3 1
22 4 2
22 5 1
22 6 1
22 7 1
22 8 3
22 9 1
22 10 1
22 11 2
22 12 5
22 13 1
22 14 1
22 15 5
22 16 2
22 17 1
22 18 2
22 19 1
22 20 1
22 21 1
22 23 1
22 24 1
22 25 1
22 26 1
22 27 1
22 28 1
22 29 1
22 30 1
22 31 2
22 32 2
22 33 5
22 34 2
22 35 1
22 36 1
22 37 1
22 38 4
22 39 1
22 40 5
22 41 1
22 42 1
22 43 1
22 44 1
22 45 2
22 46 2
23 1 2
23 2 1
23 5 3
23 6 3
23 7 1
23 10 3
23 11 2
23 13 1
23 14 1
23 17 4
23 19 3
23 20 3
23 21 1
23 25 2
23 26 4
23 27 1
23 28 3
23 29 4
23 31 1
23 34 1
23 35 1
23 36 5
23 38 2
23 39 4
23 44 4
23 45 2
25 2 2
25 5 2
25 6 5
25 7 1
25 11 1
25 13 1
25 17 1
25 18 2
25 19 4
25 20 3
25 23 3
25 26 4
25 27 2
25 28 3
25 29 1
25 35 1
25 36 3
25 39 3
25 44 2
25 45 3
26 1 1
26 2 1
26 5 5
26 6 5
26 7 1
26 9 1
26 11 2
26 13 1
26 17 4
26 18 1
26 19 5
26 20 2
26 21 2
26 23 5
26 25 5
26 27 2
26 28 4
26 29 2
26 31 1
26 34 1
26 35 1
26 36 5
26 38 2
26 39 5
26 44 5
26 45 5
27 2 4
27 5 2
27 6 2
27 7 2
27 11 1
27 13 5
27 14 3
27 17 1
27 18 3
27 19 2
27 20 4
27 21 1
27 23 1
27 25 3
27 26 2
27 28 2
27 29 4
27 34 1
27 35 5
27 36 1
27 38 1
27 39 1
27 44 1
27 45 3
28 2 3
28 5 2
28 6 5
28 7 2
28 10 2
28 11 2
28 13 2
28 17 4
28 18 3
28 19 3
28 20 3
28 21 2
28 23 4
28 25 2
28 26 3
28 27 2
28 29 3
28 36 3
28 38 2
28 39 2
28 44 4
28 45 3
29 2 4
29 4 1
29 5 3
29 6 1
29 7 4
29 8 1
29 11 1
29 13 3
29 14 1
29 17 1
29 18 1
29 19 1
29 20 4
29 21 2
29 23 4
29 25 1
29 26 1
29 27 3
29 28 3
29 34 1
29 35 1
29 36 1
29 38 1
29 44 2
29 45 1
30 24 1
31 1 2
31 2 2
31 3 1
31 4 3
31 8 5
31 9 1
31 10 2
31 12 2
31 16 2
31 18 3
31 20 3
31 22 2
31 23 2
31 32 2
31 34 2
31 37 1
31 38 3
31 40 3
31 41 2
31 43 1
31 45 2
32 1 2
32 3 2
32 4 5
32 8 2
32 9 2
32 12 1
32 31 1
32 33 3
32 34 2
32 37 1
32 40 5
32 41 1
32 46 1
33 1 2
33 2 2
33 4 5
33 8 5
33 9 2
33 10 2
33 11 1
33 12 5
33 14 1
33 15 3
33 16 3
33 18 3
33 20 1
33 22 5
33 31 3
33 32 3
33 34 3
33 37 3
33 38 2
33 40 5
33 43 2
34 1 1
34 2 2
34 5 1
34 6 1
34 7 1
34 8 2
34 13 1
34 16 1
34 18 1
34 19 1
34 20 1
34 22 1
34 23 1
34 25 1
34 26 1
34 27 1
34 28 1
34 29 1
34 31 3
34 32 1
34 33 4
34 35 1
34 37 2
34 38 2
34 40 1
34 42 5
34 43 1
35 2 3
35 13 2
35 18 2
35 27 4
35 29 2
35 39 2
36 2 1
36 5 3
36 6 5
36 17 3
36 18 1
36 19 4
36 20 1
36 21 1
36 23 5
36 25 4
36 26 5
36 28 4
36 29 2
36 39 4
36 44 5
36 45 5
37 1 2
37 2 1
37 8 2
37 9 1
37 10 2
37 12 2
37 18 1
37 31 2
37 32 1
37 33 1
37 34 2
37 40 1
37 43 1
38 2 5
38 4 2
38 6 2
38 7 4
38 8 2
38 11 3
38 13 2
38 14 4
38 18 1
38 19 2
38 20 3
38 22 5
38 23 3
38 26 2
38 28 1
38 29 3
38 31 3
38 33 3
38 34 2
38 35 5
38 41 4
38 44 1
38 45 2
39 5 3
39 6 5
39 13 1
39 17 1
39 19 5
39 23 4
39 25 2
39 26 4
39 28 2
39 36 3
39 44 4
39 45 5
40 1 1
40 2 1
40 4 5
40 8 3
40 9 1
40 12 1
40 15 3
40 16 2
40 18 1
40 20 1
40 22 3
40 31 2
40 32 5
40 33 5
40 34 2
40 37 2
40 43 1
41 1 2
41 2 2
41 8 3
41 10 5
41 12 2
41 14 2
41 20 2
41 38 3
41 43 2
42 8 1
42 10 1
42 28 1
42 31 1
42 33 1
42 34 4
42 37 1
42 41 1
42 43 1
42 45 1
43 8 2
43 12 2
43 31 1
43 33 2
43 34 1
44 1 1
44 2 1
44 5 3
44 6 5
44 7 1
44 8 1
44 11 1
44 13 1
44 17 3
44 19 5
44 20 2
44 21 2
44 23 3
44 25 2
44 26 4
44 28 2
44 33 1
44 34 1
44 35 1
44 36 4
44 38 1
44 39 4
44 42 1
44 43 1
44 45 3
45 1 1
45 2 2
45 4 1
45 5 5
45 6 5
45 7 2
45 8 1
45 9 1
45 10 1
45 11 3
45 12 2
45 13 1
45 14 2
45 17 4
45 18 2
45 19 4
45 20 4
45 21 3
45 22 1
45 23 3
45 25 4
45 26 5
45 27 2
45 28 3
45 29 3
45 31 3
45 33 1
45 34 1
45 35 1
45 36 5
45 38 2
45 42 1
45 44 4
46 1 3
46 3 4
46 8 1
46 9 3
46 12 5
46 22 1
46 32 2
46 33 2
46 34 2
46 37 1
46 43 1
<html>
<head>
<title>Delete nodes and edges</title>
<meta charset="utf-8" />
<script src="http://d3js.org/d3.v3.min.js" type="text/JavaScript"></script>
</head>
<style>
svg {
height: 500px;
width: 500px;
border: 1px solid gray;
}
</style>
<body>
<div id="viz">
<svg>
</svg>
</div>
</body>
<footer>
<script>
d3.csv("firm.csv",function(error,data) {createNetwork(data)});
function createNetwork(edgelist) {
var nodeHash = {};
var nodes = [];
var edges = [];
edgelist.forEach(function (edge) {
if (!nodeHash[edge.source]) {
nodeHash[edge.source] = {id: edge.source, label: edge.source};
nodes.push(nodeHash[edge.source]);
}
if (!nodeHash[edge.target]) {
nodeHash[edge.target] = {id: edge.target, label: edge.target};
nodes.push(nodeHash[edge.target]);
}
if (edge.weight >= 5) {
edges.push({id: nodeHash[edge.source].id + "-" + nodeHash[edge.target].id, source: nodeHash[edge.source], target: nodeHash[edge.target], weight: edge.weight});
}
});
createForceNetwork(nodes, edges);
}
function createForceNetwork(nodes, edges) {
//create a network from an edgelist
//Highlight edges, delete nodes and edges
var force = d3.layout.force().nodes(nodes).links(edges)
.size([500,500])
.charge(function (d) {return Math.min(-100, d.weight * -50)})
.on("tick", updateNetwork);
var edgeEnter = d3.select("svg").selectAll("g.edge")
.data(edges, function (d) {return d.id})
.enter()
.append("g")
.attr("class", "edge");
edgeEnter
.append("line")
.attr("class", "highlight")
.style("stroke-width", "8px")
.style("stroke", "#66CCCC")
.style("opacity", 0)
.on("dblclick", deleteEdge)
.on("mouseover", edgeOver)
.on("mouseout", edgeOut);
edgeEnter
.append("line")
.style("stroke-width", "1px")
.style("stroke", "black")
.style("pointer-events", "none");
var nodeEnter = d3.select("svg").selectAll("g.node")
.data(nodes, function (d) {return d.id})
.enter()
.append("g")
.attr("class", "node")
.on("dblclick", deleteNode)
.on("mouseover", nodeOver)
.on("mouseout", nodeOut)
.call(force.drag());
nodeEnter.append("circle")
.attr("r", 5)
.style("fill", "#CC9999")
.style("stroke", "black")
.style("stroke-width", "1px")
nodeEnter.append("text")
.style("text-anchor", "middle")
.attr("y", 2)
.style("stroke-width", "1px")
.style("stroke-opacity", 0.75)
.style("stroke", "white")
.style("font-size", "8px")
.text(function (d) {return d.id})
.style("pointer-events", "none")
nodeEnter.append("text")
.style("text-anchor", "middle")
.attr("y", 2)
.style("font-size", "8px")
.text(function (d) {return d.id})
.style("pointer-events", "none")
force.start();
function nodeOver() {
d3.select(this).select("circle")
.style("fill", "#66CCCC")
.style("stroke", "#66CCCC")
.style("stroke-width", "3px");
}
function nodeOut() {
d3.selectAll("circle")
.style("fill", "#CC9999")
.style("stroke", "black")
.style("stroke-width", "1px");
}
function deleteNode(d) {
var currentNodes = d3.selectAll("g.node").data(); //grab all data from DOM
var currentEdges = d3.selectAll("g.edge").data();
var filteredNodes = currentNodes.filter(function (p) {return p !== d});
var filteredEdges = currentEdges.filter(function (p) {return p.source !== d && p.target !== d});
force.stop(); //important
force.nodes(filteredNodes); //reapply filtered nodes to force
force.links(filteredEdges);
d3.selectAll("g.node").data(filteredNodes, function (d) {return d.id})
.exit()
.transition()
.duration(500)
.style("opacity", 0)
.remove(); // remove no longer represented nodes
d3.selectAll("g.edge").data(filteredEdges, function (d) {return d.id})
.exit()
.transition()
.duration(500)
.style("opacity", 0)
.remove();
force.start(); // remove edges no longer represented
}
// delete edges that were connected to nodes
function deleteEdge(d) {
var currentEdges = d3.selectAll("g.edge").data();
var filteredEdges = currentEdges.filter(function (p) {return p !== d});
force.stop();
force.links(filteredEdges);
d3.selectAll("g.edge").data(filteredEdges, function (d) {return d.id})
.exit()
.transition()
.duration(500)
.style("opacity", 0)
.remove();
force.start(); // restart force
}
function edgeOver(d) {
d3.select(this).style("opacity", 0.75);
}
function edgeOut() {
d3.selectAll("line.highlight").style("opacity", 0);
}
function updateNetwork() {
d3.select("svg").selectAll("line")
.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});
d3.select("svg").selectAll("g.node")
.attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"});
d3.select("svg").selectAll("g.node > circle")
.attr("r", function (d) {return Math.max(3, d.weight)});
}
}
</script>
</footer>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment