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.
<html>
<head>
<title>Delete nodes and edges</title>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></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();
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();
force.nodes(filteredNodes);
force.links(filteredEdges);
d3.selectAll("g.node").data(filteredNodes, function (d) {return d.id})
.exit()
.transition()
.duration(500)
.style("opacity", 0)
.remove();
d3.selectAll("g.edge").data(filteredEdges, function (d) {return d.id})
.exit()
.transition()
.duration(500)
.style("opacity", 0)
.remove();
force.start();
}
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();
}
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>
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