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.06988382 0.5310508 b 2 7 0.33260115 0.6985749 2
## 3 0.06988382 0.5310508 b 2 7 0.51253630 0.2101922 2
## 4 0.06988382 0.5310508 b 2 7 0.00000000 1.0000000 2
## 5 0.09663049 0.1981104 b 3 10 0.33260115 0.6985749 3
## 6 0.09663049 0.1981104 b 3 10 0.06988382 0.5310508 1
## 7 0.09663049 0.1981104 b 3 10 0.51253630 0.2101922 2
## type
## 2 x
## 3 y
## 4 z
## 5 z
## 6 y
## 7 y
The next rows of the data frame contain the actual edges:
tail(ggnetwork(n))
## x y family importance vertex.names xend yend day
## 51 0.3470495 0.7938100 b 3 5 0.3470495 0.7938100 NA
## 61 0.7147970 0.6360043 a 2 6 0.7147970 0.6360043 NA
## 71 0.1712591 0.4108127 b 2 7 0.1712591 0.4108127 NA
## 81 1.0000000 0.5759609 a 2 8 1.0000000 0.5759609 NA
## 91 0.7239504 0.9909025 c 2 9 0.7239504 0.9909025 NA
## 101 0.3025580 0.0000000 b 3 10 0.3025580 0.0000000 NA
## type
## 51 <NA>
## 61 <NA>
## 71 <NA>
## 81 <NA>
## 91 <NA>
## 101 <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()