-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathggraph.html
344 lines (282 loc) · 15.2 KB
/
ggraph.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
<title>ggplot2 extensions: ggraph</title>
<script src="libs/jquery-1.11.0/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="libs/bootstrap-3.3.1/css/cosmo.min.css" rel="stylesheet" />
<script src="libs/bootstrap-3.3.1/js/bootstrap.min.js"></script>
<script src="libs/bootstrap-3.3.1/shim/html5shiv.min.js"></script>
<script src="libs/bootstrap-3.3.1/shim/respond.min.js"></script>
<!-- Styles for this site -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/styles.css" rel="stylesheet">
<!-- Polyfill JS -->
<script src="js/polyfill.js"></script>
<style type="text/css">code{white-space: pre;}</style>
<link rel="stylesheet"
href="libs/highlight/textmate.css"
type="text/css" />
<script src="libs/highlight/highlight.js"></script>
<style type="text/css">
pre:not([class]) {
background-color: white;
}
</style>
<script type="text/javascript">
if (window.hljs && document.readyState && document.readyState === "complete") {
window.setTimeout(function() {
hljs.initHighlighting();
}, 0);
}
</script>
</head>
<body>
<style type = "text/css">
.main-container {
max-width: 940px;
margin-left: auto;
margin-right: auto;
}
code {
color: inherit;
background-color: rgba(0, 0, 0, 0.04);
}
img {
max-width:100%;
height: auto;
}
</style>
<div class="container-fluid main-container">
<!--html_preserve-->
<div class="header">
<nav class="navbar">
<h3 class="navbar-left"><strong>ggplot2</strong> extensions</h3>
<ul class="nav nav-pills navbar-right">
<li role="presentation" id="nav-home"><a href="index.html">Home</a></li>
<li role="presentation" id="nav-showcase"><a href="ggiraph.html">Extensions</a></li>
<li role="presentation" id="nav-github"><a href="https://github.com/ggplot2-exts/ggplot2-exts.github.io">GitHub</a></li>
</ul>
</nav>
</div>
<div class="showcase-header">
<div id = "showcase-intro">
ggplot2 now has an official extension mechanism. This means that others can now easily create their own stats, geoms and positions, and provide them in other packages. This should allow the ggplot2 community to flourish, even as less development work happens in ggplot2 itself. This page showcases these extensions.
</div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-4">
<div class="list-group">
<a href="ggiraph.html" class="list-group-item">
<h5 class="list-group-item-heading">ggiraph</h5>
<p class="list-group-item-text">Make ggplot interactive</p>
</a>
<a href="ggstance.html" class="list-group-item">
<h5 class="list-group-item-heading">ggstance</h5>
<p class="list-group-item-text">Horizontal versions of ggplot2 geoms</p>
</a>
<a href="ggalt.html" class="list-group-item">
<h5 class="list-group-item-heading">ggalt</h5>
<p class="list-group-item-text">Extra coordinate systems, geoms & stats</p>
</a>
<a href="ggforce.html" class="list-group-item">
<h5 class="list-group-item-heading">ggforce</h5>
<p class="list-group-item-text">Accelarating ggplot2</p>
</a>
<a href="ggrepel.html" class="list-group-item">
<h5 class="list-group-item-heading">ggrepel</h5>
<p class="list-group-item-text">Repel overlapping text labels</p>
</a>
<a href="ggraph.html" class="list-group-item">
<h5 class="list-group-item-heading">ggraph</h5>
<p class="list-group-item-text">Plot graph-like data structures</p>
</a>
<a href="ggpmisc.html" class="list-group-item">
<h5 class="list-group-item-heading">ggpmisc</h5>
<p class="list-group-item-text">Miscellaneous extensions to ggplot2</p>
</a>
<a href="geomnet.html" class="list-group-item">
<h5 class="list-group-item-heading">geomnet</h5>
<p class="list-group-item-text">Network visualizations in ggplot2</p>
</a>
<a href="ggExtra.html" class="list-group-item">
<h5 class="list-group-item-heading">ggExtra</h5>
<p class="list-group-item-text">Marginal density plots or histograms</p>
</a>
<a href="gganimate.html" class="list-group-item">
<h5 class="list-group-item-heading">gganimate</h5>
<p class="list-group-item-text">Create easy animations with ggplot2</p>
</a>
<a href="plotROC.html" class="list-group-item">
<h5 class="list-group-item-heading">plotROC</h5>
<p class="list-group-item-text">Interactive ROC plots</p>
</a>
<a href="ggthemes.html" class="list-group-item">
<h5 class="list-group-item-heading">ggthemes</h5>
<p class="list-group-item-text">ggplot themes and scales</p>
</a>
<a href="ggspectra.html" class="list-group-item">
<h5 class="list-group-item-heading">ggspectra</h5>
<p class="list-group-item-text">Extensions for radiation spectra</p>
</a>
<a href="ggnetwork.html" class="list-group-item">
<h5 class="list-group-item-heading">ggnetwork</h5>
<p class="list-group-item-text">Geoms to plot networks with ggplot2</p>
</a>
</div> <!-- list-group -->
</div> <!-- col-sm-4 -->
<div id="ggraph" class="col-sm-8">
<h3>ggraph</h3>
<p><a href="https://github.com/thomasp85/ggraph" class="uri">https://github.com/thomasp85/ggraph</a></p>
<p>ggraph extends the grammar of graphics provided by ggplot2 to cover graph and network data. This type of data consists of nodes and edges and are not optimally stored in a single data.frame, as expected by ggplot2. Furthermore the spatial position of nodes (end thereby edges) are more often defined by the graph structure through a layout function, rather than mapped to specific parameters. ggraph handles all of these issues in an extensible way that lets the user gradually build up their graph visualization with different layers as expected from ggplot2, without needing to worry too much about how positions and other metrics are derived.</p>
<p>While node-edge diagrams are the visualization people often relate to graph visualizations it is by far the only one, and ggraph have, or will have support for all types of common and uncommon visualization types.</p>
<div id="a-simple-example" class="section level4">
<h4>A simple example</h4>
<pre class="r"><code>library(ggraph)
library(igraph)
# To show a simple example of the API we consider a hierarchy
## Create a graph of the flare class hierarchy
flareGraph <- graph_from_data_frame(flare$edges, vertices = flare$vertices)
ggraph(flareGraph, 'igraph', algorithm = 'tree') +
geom_edge_link() +
ggforce::theme_no_axes()</code></pre>
<p><img src="ggraph_files/figure-html/unnamed-chunk-1-1.png" title="" alt="" width="576" /></p>
<p>Here we use the reingold-tilford algorithm to position the nodes in a hierarchy and draw straight edges between them using the <code>geom_edge_link</code> function. There are ample opportunity for modifications though:</p>
<pre class="r"><code>ggraph(flareGraph, 'igraph', algorithm = 'tree', circular = TRUE) +
geom_edge_diagonal(aes(alpha = ..index..)) +
coord_fixed() +
scale_edge_alpha('Direction', guide = 'edge_direction') +
geom_node_point(aes(filter = degree(flareGraph, mode = 'out') == 0),
color = 'steelblue', size = 1) +
ggforce::theme_no_axes()</code></pre>
<p><img src="ggraph_files/figure-html/unnamed-chunk-2-1.png" title="" alt="" width="576" /></p>
<p>Here we transform the layout into a circular representation and choose to draw the edges as diagonals instead of straight lines using <code>geom_edge_diagonal</code>. We indicate the direction of the edge by mapping the alpha value to it, and shows this using the edge_direction guide. Lastly we plot the leaf nodes using a filter function.</p>
</div>
<div id="other-layouts" class="section level4">
<h4>Other layouts</h4>
<p>But what if my data is not hierarchical, you ask. Well ggraph have access to all the layouts implemented in igraph, and then some (more on that later). To show this we take a look at some colonial Americans:</p>
<pre class="r"><code>whigsGraph <- graph_from_adjacency_matrix(whigs %*% t(whigs), mode = 'upper',
weighted = TRUE, diag = FALSE)
V(whigsGraph)$degree <- degree(whigsGraph)
ggraph(whigsGraph, 'igraph', algorithm = 'kk') +
geom_edge_link0(aes(width = weight), edge_alpha = 0.1) +
geom_node_point(aes(size = degree), colour = 'forestgreen') +
geom_node_text(aes(label = name, filter = degree > 150), color = 'white',
size = 3) +
ggforce::theme_no_axes()</code></pre>
<p><img src="ggraph_files/figure-html/unnamed-chunk-3-1.png" title="" alt="" width="576" /></p>
<p>So it seems Paul Reveres was really in the center of it all (more on this <a href="http://kieranhealy.org/blog/archives/2013/06/09/using-metadata-to-find-paul-revere/">here</a>).</p>
<p>Here we use the kamada kawai layout to lay out the nodes and draw the edges using the <code>geom_edge_link0</code> (notice the trailing 0 - this is a faster version than the standard but it doesn’t support gradients along the edge). We draw the nodes scaling the size to the degree and lastly we add node labels to the nodes with a degree larger than 150.</p>
<p><em>What if I don’t like nodes and edges?</em></p>
<p>Well you could try to make a treemap. Let’s turn to our flare hierarchy again:</p>
<pre class="r"><code># Well add some additional information using the treeApply helpers
flareGraph <- treeApply(flareGraph, function(node, parent, depth, tree) {
tree <- set_vertex_attr(tree, 'depth', node, depth)
if (depth == 1) {
tree <- set_vertex_attr(tree, 'class', node, V(tree)$shortName[node])
} else if (depth > 1) {
tree <- set_vertex_attr(tree, 'class', node, V(tree)$class[parent])
}
tree
})
V(flareGraph)$leaf <- degree(flareGraph, mode = 'out') == 0
ggraph(flareGraph, 'treemap', weight = 'size') +
geom_treemap(aes(fill = class, filter = leaf, alpha = depth), colour = NA) +
geom_treemap(aes(size = depth), fill = NA, colour = 'white') +
geom_node_text(aes(filter = depth == 1, label = shortName), size = 3) +
scale_fill_brewer(type = 'qual', palette = 3, guide = 'none') +
scale_size(range = c(3, 0.2), guide = 'none') +
scale_alpha(range = c(1, 0.6), guide = 'none') +
ggforce::theme_no_axes()</code></pre>
<p><img src="ggraph_files/figure-html/unnamed-chunk-4-1.png" title="" alt="" width="576" /></p>
<p><em>What if I don’t use igraph?</em></p>
<p>There is also support for dendrogram objects and almost anything else can be converted to either igraph or dendrogram. Let’s look at a dendrogram object:</p>
<pre class="r"><code>irisCluster <- hclust(dist(iris[, -5]), method = 'average')
irisCluster <- as.dendrogram(irisCluster)
# treeApply also works for dendrogram
irisCluster <- treeApply(irisCluster, function(node, children, ...) {
if (is.leaf(node)) {
index <- as.integer(attr(node, 'label'))
attr(node, 'nodePar') <- list(species = as.character(iris$Species[index]))
} else {
childSpecies <- sapply(children, function(child) {
attr(child, 'nodePar')$species
})
if (length(unique(childSpecies)) == 1 && !anyNA(childSpecies)) {
attr(node, 'nodePar') <- list(species = childSpecies[1])
} else {
attr(node, 'nodePar') <- list(species = NA)
}
}
node
}, direction = 'up')
ggraph(irisCluster, 'dendrogram', repel = TRUE, ratio = 10) +
geom_edge_elbow2(aes(colour = node.species),
data = gEdges('long', nodePar = 'species')) +
scale_edge_colour_brewer('Species', type = 'qual', na.value = 'black') +
ggforce::theme_no_axes()</code></pre>
<p><img src="ggraph_files/figure-html/unnamed-chunk-5-1.png" title="" alt="" width="576" /></p>
<p>Wait, what is that data argument? Most edge geoms comes in three flavors, a standard, a fast (the 0 one) and a slow (the 2 one). So why use the slow? It makes it possible to set interpolate edge aesthetics between the start and end point. Here we tell that colour should be mapped to the species of the nodes, and we tell that the edge data should contain the species parameter from the start and end nodes within the <code>gEdges()</code> call. Now we get a nice gradient from clusters with a common species towards clusters with mixed species.</p>
<p>These are just a couple of examples of what is possible. Due to the layer approach to plotting edges and nodes you have full control over the look of your plot in a very expressive way. As it is a direct extension of ggplot2, it also comes with all the niceties from there, e.g. facetting:</p>
<pre class="r"><code>highschoolGraph <- graph_from_data_frame(highschool)
ggraph(highschoolGraph, 'igraph', algorithm = 'kk') +
geom_edge_fan(aes(alpha = ..index..)) +
facet_wrap(~year) +
ggforce::theme_no_axes()</code></pre>
<p><img src="ggraph_files/figure-html/unnamed-chunk-6-1.png" title="" alt="" width="576" /></p>
</div>
</div> <!-- col-sm-8 -->
</div> <!-- row -->
</div>
</div> <!-- showcase-header -->
<!--/html_preserve-->
</div> <!-- page-body -->
<footer>
<div> </div>
<div> </div>
<div class="text-muted">
Design inspired by <a href="http://www.htmlwidgets.org/index.html" target="_blank">Ramnath Vaidyanathan, Kenton Russell, and RStudio, Inc</a>.
</div>
<div class="text-muted">
Maintained by <a href="http://www.danielemaasit.com" target="_blank">Daniel Emaasit</a>.
</div>
<div class="text-muted">
Copyright © 2016 The R Community.
</div>
</footer>
<script>
// manage active state of headres and navigation based on current page
$(document).ready(function () {
// compute name of page
href = window.location.pathname;
href = href.substr(href.lastIndexOf('/') + 1);
if (href == "")
href = "index.html";
// main navigation and headers
if (href.startsWith("index")) {
$('#nav-home').addClass('active');
$('.title').addClass('hidden');
} else if (href.startsWith("showcase")) {
$('#nav-showcase').addClass('active');
$("#page-body").detach().appendTo('#showcase-body');
$('.showcase-header').removeClass('hidden');
$('.title').addClass('hidden');
} else if (href.startsWith("develop")) {
$('#nav-develop').addClass('active');
}
// submenu navigation (used by showcase and develop)
$('.list-group a[href="' + href + '"]').addClass('active');
});
</script>
</div>
<script>
// add bootstrap table styles to pandoc tables
$(document).ready(function () {
$('tr.header').parent('thead').parent('table').addClass('table table-condensed');
});
</script>
</body>
</html>