Main building blocks
ggnetwork
The ggnetwork
package is organised around a ‘workhorse’
function of the same name, which will ‘flatten’ the network object to a
data frame that contains the edge list of the network, along with the
edge attributes and the vertex attributes of the sender nodes.
The network object referred to above might be an object of class
network
, or any data structure that can be coerced to it,
such as an edge list, an adjacency matrix or an incidence matrix. If the
intergraph
package is installed, then objects of class
igraph
can also be used with the ggnetwork
package.
The data frame returned by ggnetwork
also contains the
coordinates needed for node placement as columns "x"
,
"y"
, "xend"
and "yend"
, which as
a consequence are “reserved” names in the context of
ggnetwork
. If these names show up in the edge or the vertex
attributes, the function will simply fail to work.
The default node placement algorithm used by ggnetwork
to produce these coordinates is the Fruchterman-Reingold force-directed
layout algorithm. All of the placement
algorithms implemented in the sna
package are available
through ggnetwork
, which also accepts additional layout
parameters:
ggnetwork(n, layout = "fruchtermanreingold", cell.jitter = 0.75)
ggnetwork(n, layout = "target", niter = 100)
The layout
argument will also accept user-submitted
coordinates as a two-column matrix with as many rows as the number of
nodes in the network.
The top of the data frame produced by ggnetwork
contains
self-loops to force every node to be included in the plot. This explains
why the rows shown below have the same values in "x"
and
"xend"
(and in "y"
and "yend"
),
and only missing values in the columns corresponding to the edge
attributes:
head(ggnetwork(n))
## x y family importance vertex.names xend yend day
## 2 0.06153741 0.7570453 a 2 3 0.0000000 1.0000000 1
## 3 0.08938645 0.5007880 a 2 9 0.0000000 1.0000000 3
## 4 0.08938645 0.5007880 a 2 9 0.5949937 0.6871140 3
## 5 0.08938645 0.5007880 a 2 9 0.4826225 0.4549953 2
## 6 0.08938645 0.5007880 a 2 9 0.4988651 0.1265779 2
## 8 0.48262251 0.4549953 c 1 6 0.1570683 0.0000000 1
## type
## 2 z
## 3 y
## 4 y
## 5 z
## 6 x
## 8 y
The next rows of the data frame contain the actual edges:
tail(ggnetwork(n))
## x y family importance vertex.names xend yend
## 51 0.00000000 0.7370770 a 3 5 0.00000000 0.7370770
## 61 0.38729137 0.5340420 c 1 6 0.38729137 0.5340420
## 7 0.56327197 0.3433634 b 3 7 0.56327197 0.3433634
## 81 0.62924005 0.7626922 a 1 8 0.62924005 0.7626922
## 91 0.01230182 0.3354880 a 2 9 0.01230182 0.3354880
## 101 0.86944917 0.1852995 c 1 10 0.86944917 0.1852995
## day type
## 51 NA <NA>
## 61 NA <NA>
## 7 NA <NA>
## 81 NA <NA>
## 91 NA <NA>
## 101 NA <NA>
The data frame returned by ggnetwork
has (N +
E) rows, where N is the number of nodes of the
network, and E its number of edges. This data format is very
likely to include duplicate information about the nodes, which is
unavoidable.
Note that ggnetwork
does not include any safety
mechanism against duplicate column names. As a consequence, if there is
both a vertex attribute called "na"
and an edge attribute
called "na"
, as in the example above, then the vertex
attribute will be renamed "na.x"
and the edge attribute
will be renamed "na.y"
.
fortify.network
and fortify.igraph
The ‘flattening’ process described above is implemented by
ggnetwork
as fortify
methods that are
recognised by ggplot2
. As a result, ggplot2
will understand the following syntax as long as n
is an
object of class network
or of class
igraph
:
ggplot(n)
However, if the object n
is a matrix or an edge list to
be coerced to a network object, you are required to use the
ggnetwork
function to pass the object to
ggplot2
:
ggplot(ggnetwork(n))
geom_edges
Let’s now draw the network edges using geom_edges
, which
is just a lightly hacked version of geom_segment
. In the
example below, we map the type
edge attribute to the
linetype of the network edges:
ggplot(n, aes(x = x, y = y, xend = xend, yend = yend)) +
geom_edges(aes(linetype = type), color = "grey50") +
theme_blank()
The other aesthetics that we mapped are the basic coordinates of the
network plot. These might also be set as part of the call to
geom_segment
, but setting them at the root of the plot
avoids having to repeat them in additional geoms.
Note that geom_edges
can also produce curved edges by
setting its curvature
argument to any value above
0
(the default):
ggplot(n, aes(x = x, y = y, xend = xend, yend = yend)) +
geom_edges(aes(linetype = type), color = "grey50", curvature = 0.1) +
theme_blank()
geom_nodes
Let’s now draw the nodes using geom_nodes
, which is just
a lightly hacked version of geom_point
. In the example
below, we map the family
vertex attribute to the color of
the nodes, and make the size of these nodes proportional to the
importance
vertx attribute:
ggplot(n, aes(x = x, y = y, xend = xend, yend = yend)) +
geom_edges(aes(linetype = type), color = "grey50") +
geom_nodes(aes(color = family, size = importance)) +
theme_blank()