-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathggraph.R
150 lines (150 loc) · 7.55 KB
/
ggraph.R
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
#' Create a ggraph plot
#'
#' This function is the equivalent of [ggplot2::ggplot()] in ggplot2.
#' It takes care of setting up the plot object along with creating the layout
#' for the plot based on the graph and the specification passed in.
#' Alternatively a layout can be prepared in advance using
#' `create_layout` and passed as the data argument. See *Details* for
#' a description of all available layouts.
#'
#' @details
#' Following is a short description of the different layout types available in
#' ggraph. Each layout is further described in its own help pages. Any type of
#' regular graph/network data can be represented as a tbl_graph object. Because
#' of this the different layouts that can be applied to tbl_graph
#' objects are quite diverse, but not all layouts makes sense to all types of
#' graphs. It is up to the user to understand their data and choose an
#' appropriate layout. For standard node-edge diagrams igraph defines a
#' long range of different layout functions that are all available through the
#' `igraph` layout where the specific layout is specified using the
#' `algorithm` argument. In order to minimize typing all igraph algorithms
#' can also be passed directly into the `layout` argument.
#'
#' Any object that has an appropriate `as_tbl_graph` method can be passed
#' into `ggraph()` and will automatically be converted underneath.
#'
#' \describe{
#' \item{`auto`}{The default layout. See [layout_tbl_graph_auto()] for further
#' details}
#' \item{`igraph`}{Use one of the internal igraph layout algorithms.
#' The algorithm is specified using the `algorithm` argument. All strings
#' accepted by the `algorithm` argument can also be supplied directly
#' into `layout`. See [layout_tbl_graph_igraph()] for further
#' details}
#' \item{`dendrogram`}{Lays out the nodes in a tree-like graph as a
#' dendrogram with leaves set at 0 and parents 1 unit above its tallest child.
#' See [layout_tbl_graph_dendrogram()] for further details}
#' \item{`manual`}{Lets the user manually specify the location of each
#' node. See [layout_tbl_graph_manual()] for further details}
#' \item{`linear`}{Arranges the nodes linearly or circularly in order to
#' make an arc diagram. See [layout_tbl_graph_linear()] for further
#' details}
#' \item{`matrix`}{Arranges nodes on a diagonal thus preparing it for use with
#' [geom_edge_point()] to make a matrix plot. See [layout_tbl_graph_matrix()]
#' for further details}
#' \item{`treemap`}{Creates a treemap from the graph, that is, a
#' space-filing subdivision of rectangles showing a weighted hierarchy. See
#' [layout_tbl_graph_treemap()] for further details}
#' \item{`circlepack`}{Creates a layout showing a hierarchy as circles
#' within circles. Conceptually equal to treemaps. See
#' [layout_tbl_graph_circlepack()] for further details}
#' \item{`partition`}{Create icicle or sunburst charts, where each layer
#' subdivides the division given by the preceding layer. See
#' [layout_tbl_graph_partition()] for further details}
#' \item{`hive`}{Positions nodes on axes spreading out from the center
#' based on node attributes. See [layout_tbl_graph_hive()] for further
#' details}
#' \item{`cactustree`}{Positions nodes as circles on the periphery of their
#' parent circle. See [layout_tbl_graph_cactustree()] for further
#' details}
#' \item{`backbone`}{Layout optimised for highly connected small-world graphs
#' such as social networks. See [layout_tbl_graph_backbone()] for further
#' details}
#' \item{`centrality`}{Place nodes around origin based on their centrality.
#' See [layout_tbl_graph_centrality()] for further
#' details}
#' \item{`eigen`}{Spectral layout based on the eigenvector of a matrix
#' representation of the graph. See [layout_tbl_graph_eigen()] for further
#' details}
#' \item{`fabric`}{Draw nodes as horizontal lines and connect them with
#' vertical lines if an edge exists between them. See
#' [layout_tbl_graph_fabric()] for further
#' details}
#' \item{`focus`}{Place nodes around a focus node based on their distance to
#' that node. See [layout_tbl_graph_focus()] for further
#' details}
#' \item{`pmds`}{Layout based on multidimensional scaling of a set of pivot
#' nodes, allowing MDS layout to be used on larger graphs. See
#' [layout_tbl_graph_pmds()] for further
#' details}
#' \item{`stress`}{Layout based on stress minimisation with better stability
#' than Kamada-Kawai layout. See [layout_tbl_graph_stress()] for further
#' details}
#' \item{`unrooted`}{Draws unrooted trees based on equal angle with optional
#' equal daylight modification. See [layout_tbl_graph_unrooted()] for further
#' details}
#' \item{`htree`}{Draws binary trees as a space filling fractal. See
#' [layout_tbl_graph_htree()] for further details}
#' }
#'
#' Alternatively a matrix or a data.frame can be provided to the `layout`
#' argument. In the former case the first column will be used as x coordinates
#' and the second column will by used as y coordinates, further columns are
#' dropped. In the latter case the data.frame is used as the layout table and
#' must thus contain a numeric x and y column.
#'
#' Lastly a function can be provided to the `layout` argument. It will be called
#' with the graph object as its first argument and any additional argument
#' passed into `ggraph()`/`create_layout()`. The function must return either a
#' data.frame or an object coercible to one and have an `x` and `y` column, or
#' an object coercible to a `tbl_graph`. In the latter case the node data is
#' extracted and used as layout (and must thus contain an `x` and `y` column)
#' and the graph will be added as the `graph` attribute.
#'
#' @param graph The object containing the graph. See *Details* for a list
#' of supported classes. Or a `layout_ggraph` object as returned from
#' `create_layout` in which case all subsequent arguments is ignored.
#'
#' @param layout The type of layout to create. Either a valid string, a
#' function, a matrix, or a data.frame (see Details)
#'
#' @param circular Should the layout be transformed into a radial
#' representation. Only possible for some layouts. Defaults to `FALSE`
#'
#' @param ... Arguments passed on to the layout function.
#'
#' @return For `ggraph()` an object of class gg onto which layers, scales,
#' etc. can be added. For `create_layout()` an object inheriting from
#' `layout_ggraph`. `layout_ggraph` itself inherits from
#' `data.frame` and can be considered as such. The data.frame contains
#' the node positions in the `x` and `y` column along with
#' additional columns generated by the specific layout, as well as node
#' parameters inherited from the graph. Additional information is stored as
#' attributes to the data.frame. The original graph object is stored in the
#' `graph` attribute and the `circular` attribute contains a logical
#' indicating whether the layout has been transformed to a circular
#' representation.
#'
#' @keywords layout network graph hierarchy visualisation
#'
#' @seealso [get_edges()] for extracting edge information from the
#' layout and [get_con()] for extracting path information.
#'
#' @examples
#' require(tidygraph)
#' gr <- create_notable('bull')
#' layout <- create_layout(gr, layout = 'igraph', algorithm = 'kk')
#' @export
#'
ggraph <- function(graph, layout = 'auto', ...) {
envir <- parent.frame()
p <- ggplot(data = create_layout(graph, layout, ...), environment = envir) +
th_no_axes()
class(p) <- c('ggraph', class(p))
p
}
#' @export
ggplot_build.ggraph <- function(plot) {
.register_graph_context(attr(plot$data, 'graph'), free = TRUE)
NextMethod()
}