├── .gitignore ├── .Rbuildignore ├── NAMESPACE ├── arcdiagram.Rproj ├── devtools-flow.R ├── man ├── xynodes.Rd ├── min_max_margin.Rd ├── arc_radius_locs.Rd ├── graph_info.Rd ├── above_below.Rd ├── node_coords.Rd └── arcplot.Rd ├── DESCRIPTION ├── NEWS ├── README.md ├── vignettes ├── network.Rmd ├── les-miserables.Rmd └── introduction.Rmd ├── R └── arcplot.r └── lesmiserables.gml /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | inst/doc 6 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^README.md 2 | ^devtools-flow.R 3 | ^.*\.Rproj$ 4 | ^\.Rproj\.user$ 5 | ^README\.Rmd$ 6 | ^lesmiserables.gml 7 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(above_below) 4 | export(arc_radius_locs) 5 | export(arcplot) 6 | export(graph_info) 7 | export(min_max_margin) 8 | export(node_coords) 9 | export(xynodes) 10 | -------------------------------------------------------------------------------- /arcdiagram.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /devtools-flow.R: -------------------------------------------------------------------------------- 1 | # ===================================================== 2 | # Devtools workflow 3 | # library(devtools) 4 | # ===================================================== 5 | 6 | devtools::document() # generate documentation 7 | devtools::check_man() # check documentation 8 | #devtools::test() # run tests 9 | devtools::build_vignettes() # build vignettes 10 | devtools::build() # build bundle 11 | devtools::install() # install package 12 | 13 | -------------------------------------------------------------------------------- /man/xynodes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/arcplot.r 3 | \name{xynodes} 4 | \alias{xynodes} 5 | \title{X or Y coordinates of node locations} 6 | \usage{ 7 | xynodes(num_nodes, aux_ord, labels) 8 | } 9 | \arguments{ 10 | \item{num_nodes}{number of nodes} 11 | 12 | \item{aux_ord}{vector with the index number for ordering the nodes} 13 | 14 | \item{labels}{optional string vector with labels for the nodes} 15 | } 16 | \description{ 17 | Gives axis locations of each node 18 | } 19 | -------------------------------------------------------------------------------- /man/min_max_margin.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/arcplot.r 3 | \name{min_max_margin} 4 | \alias{min_max_margin} 5 | \title{Minimum and Maximum Margin Limits} 6 | \usage{ 7 | min_max_margin(radios, above) 8 | } 9 | \arguments{ 10 | \item{radios}{vector of arc radius} 11 | 12 | \item{above}{logical vectors indicating whether arcs should be displayed} 13 | } 14 | \value{ 15 | list with minimum and maximum margin limits 16 | } 17 | \description{ 18 | Computes the minimum and maximum margin limits of 19 | plotting region 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/arc_radius_locs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/arcplot.r 3 | \name{arc_radius_locs} 4 | \alias{arc_radius_locs} 5 | \title{Arc Radius Locations} 6 | \usage{ 7 | arc_radius_locs(edgelist, nodes, centers) 8 | } 9 | \arguments{ 10 | \item{edgelist}{2-column matrix} 11 | 12 | \item{nodes}{vector of nodes} 13 | 14 | \item{centers}{vector with xy-positions of nodes} 15 | } 16 | \value{ 17 | a list with locations and radios 18 | 19 | \item{locs}{locations} 20 | 21 | \item{radios}{radius values} 22 | } 23 | \description{ 24 | Computes the location and radius of each arc 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: arcdiagram 2 | Type: Package 3 | Title: Plot pretty arc diagrams 4 | Version: 0.1.12 5 | Date: 2018-12-01 6 | Authors@R: c( 7 | person("Gaston", "Sanchez", 8 | email = "gaston.stat@gmail.com", role = c("aut", "cre")), 9 | person("Ethelon", "NA", role = "ctb")) 10 | Maintainer: Gaston Sanchez 11 | Description: Implementation of the function 'arcplot' for plotting pretty arc 12 | diagrams ('arcdiagram' can be seen as a plugin for the 'igraph' package) 13 | URL: https://github.com/gastonstat/arcdiagram 14 | Depends: 15 | R (>= 3.0) 16 | Imports: 17 | igraph 18 | Suggests: 19 | diagram, 20 | knitr, 21 | rmarkdown 22 | VignetteBuilder: knitr 23 | License: GPL-3 24 | LazyData: true 25 | Collate: 26 | 'arcplot.r' 27 | RoxygenNote: 6.0.1 28 | -------------------------------------------------------------------------------- /man/graph_info.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/arcplot.r 3 | \name{graph_info} 4 | \alias{graph_info} 5 | \title{Graph Information} 6 | \usage{ 7 | graph_info(edgelist, vertices, sorted = FALSE, decreasing = FALSE, 8 | ordering = NULL, labels = NULL) 9 | } 10 | \arguments{ 11 | \item{edgelist}{basically a two-column matrix with edges 12 | (see \code{\link{graph}})} 13 | 14 | \item{vertices}{optional vector of vertex names corresponding with 15 | those in the edgelist} 16 | 17 | \item{sorted}{logical to indicate if nodes should be sorted 18 | (default \code{FALSE})} 19 | 20 | \item{decreasing}{logical to indicate type of sorting 21 | (used only when \code{sorted=TRUE})} 22 | 23 | \item{ordering}{optional numeric or string vector providing the 24 | ordering of nodes. When provided, this parameter overrides 25 | \code{sorted=TRUE}). See the details section for more information.} 26 | 27 | \item{labels}{optional string vector with labels for the nodes} 28 | } 29 | \description{ 30 | Gets graph information 31 | } 32 | \keyword{internal} 33 | -------------------------------------------------------------------------------- /man/above_below.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/arcplot.r 3 | \name{above_below} 4 | \alias{above_below} 5 | \title{Above or Below} 6 | \usage{ 7 | above_below(edgelist, above) 8 | } 9 | \arguments{ 10 | \item{edgelist}{two-column matrix} 11 | 12 | \item{above}{optional numeric or logical vector indicating what edges 13 | (arcs) should be plotted above (or to the right of) of chosen axis 14 | If \code{above = NULL} then all arcs are plotted above (or to the right) 15 | If \code{above} is numeric, it cannot contain both positive and negative 16 | indices. 17 | If \code{above} is logical, its length must equal the number of rows in 18 | \code{edgelist}} 19 | } 20 | \value{ 21 | a logical vector indicating how arcs should be displayed 22 | } 23 | \description{ 24 | Determines how arcs should be displayed 25 | } 26 | \details{ 27 | If \code{horizontal = TRUE} then arcs can be plotted above or 28 | below the horizontal axis \cr 29 | If \code{horizontal = FALSE} then arcs can be plotted to the right or 30 | left of the vertical axis 31 | } 32 | \keyword{internal} 33 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Version 0.1.11 (2014-04-15) 2 | ------------------------------------------------------------ 3 | 4 | * modify name of vignette file 5 | 6 | 7 | Version 0.1.9 (2014-03-24) 8 | ------------------------------------------------------------ 9 | 10 | * new parameter `above` to specify display of arcs 11 | 12 | * change function `node_coords` to replace old `xynodes` 13 | 14 | 15 | Version 0.1.8 (2014-03-23) 16 | ------------------------------------------------------------ 17 | 18 | * parameter `ordering` now accepts strings 19 | 20 | 21 | Version 0.1.6 (2013-02-11) 22 | ------------------------------------------------------------ 23 | 24 | * `xynodes`: fixing a bug in the way of getting the nodes 25 | 26 | Version 0.1.5 (2013-02-02) 27 | ------------------------------------------------------------ 28 | 29 | * `arcplot`: fixing a typo in the documentation 30 | 31 | Version 0.1.4 (2013-02-01) 32 | ------------------------------------------------------------ 33 | 34 | * more elegant way to get coordinates of arcs 35 | 36 | Version 0.1.3 (2013-01-30) 37 | ------------------------------------------------------------ 38 | 39 | * allow vertical orientation of arc diagrams 40 | 41 | * rename function `xnodes` into `xynodes` 42 | 43 | Version 0.1.2 (2013-01-29) 44 | ------------------------------------------------------------ 45 | 46 | * change the way nodes are extracted in `arcplot` 47 | 48 | Version 0.1.1 (2013-01-28) 49 | ------------------------------------------------------------ 50 | 51 | * first stable version of arcdiagram -------------------------------------------------------------------------------- /man/node_coords.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/arcplot.r 3 | \name{node_coords} 4 | \alias{node_coords} 5 | \title{Node Coordinates} 6 | \usage{ 7 | node_coords(edgelist, sorted = FALSE, decreasing = FALSE, ordering = NULL, 8 | labels = NULL) 9 | } 10 | \arguments{ 11 | \item{edgelist}{basically a two-column matrix with edges 12 | (see \code{\link{graph}})} 13 | 14 | \item{sorted}{logical to indicate if nodes should be sorted} 15 | 16 | \item{decreasing}{logical to indicate type of sorting 17 | (used only when \code{sorted=TRUE})} 18 | 19 | \item{ordering}{optional numeric vector providing the ordering of nodes 20 | (when provided, this parameter overrides \code{sorted=TRUE})} 21 | 22 | \item{labels}{character vector with labels for the nodes} 23 | } 24 | \value{ 25 | a vector with the location of nodes in the x-axis 26 | } 27 | \description{ 28 | Computes axis locations of each node. This function can be helpful when 29 | you want to separately plot the node labels using the function mtext. 30 | } 31 | \examples{ 32 | 33 | \dontrun{ 34 | # generate a graph 35 | some_graph = graph.ring(10) 36 | 37 | # add names to nodes 38 | V(some_graph)$name = letters[1:vcount(some_graph)] 39 | 40 | # extract edgelist 41 | edgelist = get.edgelist(some_graph) 42 | 43 | # (default) arc diagram 44 | arcplot(edgelist, labels=V(some_graph)$name, las=1) 45 | 46 | # get x-axis coordinates of nodes 47 | xcoords = node_coords(edgelist, labels=V(some_graph)$name) 48 | 49 | # arc diagram with various labels 50 | arcplot(edgelist, show.labels=FALSE, show.nodes=TRUE) 51 | mtext(V(some_graph)$name, side=1, line=0, at=xcoords) 52 | mtext(rep("node",10), side=1, line=1, at=xcoords, col="gray90") 53 | } 54 | 55 | } 56 | \seealso{ 57 | \code{\link{arcplot}} 58 | } 59 | \author{ 60 | Gaston Sanchez 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `"arcdiagram"` 2 | 3 | `arcdiagram` is a minimalist package that provides a basic function to plot 4 | pretty arc diagrams in R. 5 | 6 | 7 | ## Donation 8 | 9 | As a Data Science and Statistics educator, I love to share the work I do. 10 | Each month I spend dozens of hours curating learning materials and computational 11 | tools like this R package. If you find any value and usefulness in `arcdiagram`, 12 | please consider making a 13 | one-time donation---via paypal---in any amount 14 | (e.g. the amount you would spend inviting me a coffee or any other drink). 15 | Your support really matters. 16 | 17 | 18 | 19 | 20 | 21 | 22 | ## Installation 23 | 24 | `arcdiagram` is only available in github (but not in CRAN). To install the 25 | development version, use `install_github()` from R package `"devtools"`: 26 | 27 | ```ruby 28 | # install 'arcdiagram' (development version) 29 | devtools::install_github('gastonstat/arcdiagram') 30 | ``` 31 | 32 | ## Some Examples 33 | 34 | ```ruby 35 | library(arcdiagram) 36 | 37 | # create a star graph with 10 nodes 38 | star_graph = graph.star(10, mode="out") 39 | 40 | # extract edgelist 41 | star_edges = get.edgelist(star_graph) 42 | 43 | # inspect star_edges 44 | star_edges 45 | 46 | # plot 1: default arc diagram 47 | arcplot(star_edges) 48 | 49 | # plot 2: show nodes as circles, in decreasing order 50 | arcplot(star_edges, show.nodes=TRUE, sorted=TRUE, decreasing=TRUE, las=1) 51 | 52 | # plot 3: different ordering, arc widths, arc colors, and node sizes 53 | set.seed(120) 54 | arcplot(star_edges, ordering=sample(1:10), labels=paste("node",1:10,sep="-"), 55 | lwd.arcs=4*runif(10,.5,2), col.arcs=hsv(runif(9,0.6,0.8),alpha=0.4), 56 | show.nodes=TRUE, pch.nodes=21, cex.nodes=runif(10,1,3), 57 | col.nodes="gray80", bg.nodes="gray90", lwd.nodes=2) 58 | 59 | # plot 4: same as plot 3 but vertically oriented 60 | set.seed(120) 61 | op = par(mar = c(0.5, 5, 0.5, 3)) 62 | arcplot(star_edges, ordering=sample(1:10), horizontal=FALSE, 63 | labels=paste("node",1:10,sep="-"), 64 | lwd.arcs=4*runif(10,.5,2), col.arcs=hsv(runif(9,0.6,0.8),alpha=0.4), 65 | show.nodes=TRUE, pch.nodes=21, cex.nodes=runif(10,1,3), 66 | col.nodes="gray80", bg.nodes="gray90", lwd.nodes=2) 67 | par(op) 68 | ``` 69 | -------------------------------------------------------------------------------- /man/arcplot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/arcplot.r 3 | \name{arcplot} 4 | \alias{arcplot} 5 | \title{Arc Diagram Plot} 6 | \usage{ 7 | arcplot(edgelist, vertices, sorted = FALSE, decreasing = FALSE, 8 | ordering = NULL, labels = NULL, horizontal = TRUE, above = NULL, 9 | col.arcs = "#5998ff77", lwd.arcs = 1.8, lty.arcs = 1, lend = 1, 10 | ljoin = 2, lmitre = 1, show.nodes = TRUE, pch.nodes = 19, 11 | cex.nodes = 1, col.nodes = "gray80", bg.nodes = "gray80", 12 | lwd.nodes = 1, show.labels = TRUE, col.labels = "gray55", 13 | cex.labels = 0.9, las = 2, font = 1, line = 0, outer = FALSE, 14 | adj = NA, padj = NA, axes = FALSE, xlim = NULL, ylim = NULL, ...) 15 | } 16 | \arguments{ 17 | \item{edgelist}{basically a two-column matrix with edges 18 | (see \code{\link{graph}})} 19 | 20 | \item{vertices}{optional vector of vertex names corresponding with 21 | those in the edgelist} 22 | 23 | \item{sorted}{logical to indicate if nodes should be sorted 24 | (default \code{FALSE})} 25 | 26 | \item{decreasing}{logical to indicate type of sorting 27 | (used only when \code{sorted=TRUE})} 28 | 29 | \item{ordering}{optional numeric or string vector providing the 30 | ordering of nodes. When provided, this parameter overrides 31 | \code{sorted=TRUE}). See the details section for more information.} 32 | 33 | \item{labels}{optional string vector with labels for the nodes} 34 | 35 | \item{horizontal}{logical indicating whether to plot 36 | in horizontal orientation} 37 | 38 | \item{above}{optional vector indicating which arcs should be displayed 39 | above (or to the right) and below (or to the left) of the axis} 40 | 41 | \item{col.arcs}{color for the arcs (default \code{"gray50"})} 42 | 43 | \item{lwd.arcs}{line width for the arcs (default 1)} 44 | 45 | \item{lty.arcs}{line type for the arcs (see \code{\link{par}})} 46 | 47 | \item{lend}{the line end style for the arcs (see \code{\link{par}})} 48 | 49 | \item{ljoin}{the line join style for the arcs (see \code{\link{par}})} 50 | 51 | \item{lmitre}{the line mitre limit for the arcs (see \code{\link{par}})} 52 | 53 | \item{show.nodes}{logical indicating whether to show node symbols} 54 | 55 | \item{pch.nodes}{plotting 'character', i.e. symbol to use when 56 | plotting nodes (\code{pch.nodes=0:25})} 57 | 58 | \item{cex.nodes}{expansion of the node symbols (default 1)} 59 | 60 | \item{col.nodes}{color of the node symbols (default \code{"gray50"})} 61 | 62 | \item{bg.nodes}{background (fill) color for the node symbols 63 | given by \code{pch.nodes=21:25}} 64 | 65 | \item{lwd.nodes}{line width for drawing node symbols 66 | (see \code{\link{points}})} 67 | 68 | \item{show.labels}{logical indicating whether to show node labels} 69 | 70 | \item{col.labels}{color of the node labels (default \code{"gray50"})} 71 | 72 | \item{cex.labels}{expansion of node labels (default \code{"gray50"})} 73 | 74 | \item{las}{numeric in {0,1,2,3}; the style of axis labels 75 | (see \code{\link{par}})} 76 | 77 | \item{font}{font used for node labels (see \code{\link{par}})} 78 | 79 | \item{line}{on which margin line the node labels are displayed, 80 | starting at 0 counting outwards (see \code{\link{mtext}})} 81 | 82 | \item{outer}{use outer margins, if available, to plot node labels 83 | (see \code{\link{mtext}})} 84 | 85 | \item{adj}{adjustment for each string in reading direction 86 | (see \code{\link{mtext}})} 87 | 88 | \item{padj}{adjustment for each string perpendicular to 89 | the reading direction (see \code{\link{mtext}})} 90 | 91 | \item{axes}{logical indicating whether to plot the axes 92 | (default \code{FALSE})} 93 | 94 | \item{xlim}{numeric vector of length 2, giving the x coordinates} 95 | 96 | \item{ylim}{numeric vector of length 2, giving the y coordinates} 97 | 98 | \item{...}{further graphical parameters (see \code{\link{par}}), including 99 | \code{family}, \code{xpd}, \code{main}, \code{asp}, etc.} 100 | } 101 | \description{ 102 | Give me an edgelist and I'll help you plot a pretty damn arc diagram 103 | } 104 | \details{ 105 | The arcs are scaled such that they fit in a plot region with its 106 | x-axis ranging from zero to one. Node symbols and labels can be 107 | optionally displayed. Node symbols are displayed through 108 | the function \code{points}. In turn, node labels are displayed 109 | through the function \code{mtext}. 110 | 111 | When \code{ordering} is provided in numeric format and node labels are 112 | strings, the labels are alphabetically ordered first, and then nodes are 113 | sorted according to the provided \code{ordering}. 114 | 115 | If \code{ordering} is provided in string format, the node labels must be 116 | strings as well. The nodes will be sorted according to \code{ordering}. 117 | } 118 | \examples{ 119 | 120 | \dontrun{ 121 | # create an edgelist 122 | un_graphe <- rbind( 123 | c("fromage", "pain"), 124 | c("pain", "vin"), 125 | c("vin", "biere"), 126 | c("cidre", "biere"), 127 | c("foie", "fromage"), 128 | c("pain", "foie")) 129 | 130 | # deafult arcplot 131 | arcplot(un_graphe) 132 | # vertical display 133 | arcplot(un_graphe, horizontal=FALSE) 134 | # arcplot with arcs above and below axis 135 | arcplot(un_graphe, above = c(1, 3, 5)) 136 | # nodes sorted alphabetically (increasing) 137 | arcplot(un_graphe, sorted=TRUE) 138 | # nodes sorted alphabetically (decreasing) 139 | arcplot(un_graphe, sorted=TRUE, decreasing = TRUE) 140 | # provided order for nodes 141 | new_order = c("vin", "biere", "cidre", "fromage", "foie", "pain") 142 | arcplot(un_graphe, ordering = new_order) 143 | 144 | 145 | # generate graphs 146 | ring_graph = graph.ring(10) 147 | star_graph = graph.star(10, mode="out") 148 | tree_graph = graph.tree(10, 2) 149 | 150 | # add names to nodes 151 | V(ring_graph)$name = letters[1:vcount(ring_graph)] 152 | V(star_graph)$name = paste("Node", 1:vcount(star_graph)) 153 | V(tree_graph)$name = paste("V", 1:vcount(tree_graph), sep='') 154 | 155 | # extract edgelist 156 | ring_edges = get.edgelist(ring_graph) 157 | star_edges = get.edgelist(star_graph) 158 | tree_edges = get.edgelist(tree_graph) 159 | 160 | # arc diagram 161 | arcplot(ring_edges, labels=V(ring_graph)$name, las=1) 162 | arcplot(star_edges, labels=V(star_graph)$name, las=2) 163 | arcplot(tree_edges, labels=V(tree_graph)$name, las=2) 164 | 165 | # compare to plot.igraph 166 | plot(ring_graph, vertex.label=V(ring_graph)$name) 167 | plot(star_graph, vertex.label=V(star_graph)$name) 168 | plot(tree_graph, vertex.label=V(tree_graph)$name) 169 | } 170 | 171 | } 172 | \seealso{ 173 | \code{\link{xynodes}} 174 | } 175 | \author{ 176 | Gaston Sanchez 177 | } 178 | -------------------------------------------------------------------------------- /vignettes/network.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arcdiagrams with package network" 3 | author: "Gaston Sanchez" 4 | output: rmarkdown::html_vignette 5 | vignette: > 6 | %\VignetteIndexEntry{arcdiagram with network} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | %\VignetteEncoding{UTF-8} 9 | --- 10 | 11 | ```{r, echo = FALSE, message = FALSE} 12 | knitr::opts_chunk$set(collapse = T, comment = "#>") 13 | library(igraph) 14 | library(network) 15 | library(arcdiagram) 16 | ``` 17 | 18 | ## Introduction 19 | 20 | `"arcdiagram"` is a package for producing pretty arc diagrams of graphs in R. You can think of `"arcdiagram"` as a plugin of the package `"igraph"` (by Gabor Csardi and Tamas Nepusz). In this document we will discuss how to use `"arcdiagram"` to produce arc diagrams of graphs from the package `"network"` (by Carter Butts, David Hunter, and Mark Handcock). 21 | 22 | 23 | 24 | ## R package `network` 25 | 26 | R has several packages dedicated to graphs and network analysis. There is even a __CRAN Task View__ for graphical models that you can check at: 27 | 28 | http://cran.r-project.org/web/views/gR.html 29 | 30 | `"arcdiagram"` has been designed _to fit like a glove_ for graph edge lists obtained from `"igraph"`. However, graph edge lists can also be obtained using the package `"network"`. Let's see how to play with `"arcdiagram"` and `"network"`. 31 | 32 | 33 | ### Step 1: Load packages 34 | 35 | First let's load the packages `"arcdiagram"` and `"network"` (I'm assuming you already installed them) 36 | 37 | ```{r libraries, message=FALSE} 38 | # load 'arcdiagram' 39 | library(arcdiagram) 40 | 41 | # load 'network' 42 | library(network) 43 | ``` 44 | 45 | 46 | 47 | ### Step 2: Toy example 48 | 49 | Let's start with a very simple example. We will generate a random graph with 7 nodes. One way to do this is by generating an adjacency matrix first and then create the graph with the function `network()`: 50 | 51 | ```{r toy_example} 52 | # generate a random adjacency matrix 53 | set.seed(95) 54 | toy_matrix <- matrix(rbinom(49,1,.25), 7, 7) 55 | diag(toy_matrix) = 0 56 | 57 | # create a graph from the adjacency matrix 58 | toy_graph <- network(toy_matrix, directed = FALSE) 59 | ``` 60 | 61 | 62 | ### Step 3: Extract `edgelist` 63 | 64 | Once we have the network, we need to extract the edge list which will be used as the main argument for `arcplot()`. The way to obtain an edge list from a `"network"` object is with the function `as.matrix()` and the argument `matrix.type = "edgelist"` 65 | 66 | ```{r toy_edgelist} 67 | # edgelist 68 | toy_edges <- as.matrix(toy_graph, matrix.type = "edgelist") 69 | ``` 70 | 71 | 72 | ### Step 4: Plot arc diagram 73 | 74 | The edge list `toy_edges` is all you need to produce an arc diagram with `arcplot()`: 75 | 76 | ```{r arcplot_edgelist, fig.width=6, fig.height=4, out.width='.8\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 77 | # plot arc diagram 78 | op <- par(mar = c(1, 0.5, 0.5, 0.5)) 79 | arcplot(toy_edges, las=1) 80 | par(op) 81 | ``` 82 | 83 | 84 | 85 | ## Florentine Weddings Network 86 | 87 | Let's see another example using a more interesting data set. We will use the data `"flo"` which is one of the datasets available in `"network"`. This data set consists of weddings among leading Florentine families (in Italy). 88 | 89 | 90 | ### Step 1: Data `flo` 91 | 92 | The way to get a graph (i.e. network) from the data `"flo"` is by using the function `network()`: 93 | 94 | ```{r data_flo} 95 | # load data 'flo' 96 | data(flo) 97 | 98 | # network 99 | netflo <- network(flo) 100 | 101 | # what does 'netflo' look like? 102 | netflo 103 | ``` 104 | 105 | 106 | ### Step 2: Edgelist 107 | 108 | Because the main argument for `arcplot()` is an edge list, we need to use `as.matrix()` with its argument `matrix.type = "edgelist"` to get such a list form `netflo`: 109 | 110 | ```{r flo_edgelist} 111 | # edgelist 112 | flo_edges <- as.matrix(netflo, matrix.type="edgelist") 113 | ``` 114 | 115 | Now we can get a first arc diagram: 116 | 117 | ```{r flo_plot1, fig.width=6, fig.height=4, out.width='.9\\linewidth', out.height='.6\\linewidth', fig.align='center', echo=c(1,3)} 118 | # second plot 119 | op = par(mar = c(2, 0.5, 1, 0.5)) 120 | arcplot(flo_edges, las=1) 121 | par(op) 122 | ``` 123 | 124 | 125 | ### Step 3: Node Labels 126 | 127 | If you inspect either the object `netflo` or the edgelist `flo\_edges`, you will see that we have the names of the nodes (i.e. the vertices) as an attribute, for instance: 128 | 129 | ```{r print_netflo} 130 | # print netflo 131 | netflo 132 | ``` 133 | 134 | As you can see in the last lines of the output, `netflo` contains the vertex attribute names `vertex.names`. One way to get these names is by using the function `get.vertex.attribute()`: 135 | 136 | ```{r fail_attribute} 137 | # try to get vertex names 138 | get.vertex.attribute(netflo, "vertex.names") 139 | ``` 140 | 141 | If by any chance you find an error message telling you something like this (don't panic): 142 | 143 | ``` 144 | Error in get.vertex.attribute(netflo, "vertex.names") : 145 | Not a graph object 146 | ``` 147 | 148 | The cause of the problem is a "compatibility" issue between the packages `"igraph"` and `"network"` (remember that `"arcdiagram"` depends on `"igraph"`). Both packages have the same name for some of their functions ---`get.vertex.attribute()` among them---. Actually, since we first load `"arcdiagram"`, this implies that the homonym functions of `"network"` are __masked__ by those of `"igraph"`. The solution? Use the double colon operator `::`. To get the vertex names from `netflo` we have to specify the `namespace` under which the required `get.vertex.attribute()` function is located: 149 | 150 | ```{r flo_get_vertex_names} 151 | # get vertex names 152 | flo_names <- network::get.vertex.attribute(netflo, "vertex.names") 153 | 154 | # show me the names 155 | flo_names 156 | ``` 157 | 158 | An alternative way to get the vertex names is by extracting them directly from the edge list `flo_edges` with the function `attributes()`: 159 | 160 | ```{r flo_get_labels} 161 | # another way to get vertex names 162 | attributes(flo_edges)$vnames 163 | ``` 164 | 165 | Of course, this a painless way to get the names, but I wanted to show you the hard way in case you find yourself trapped in that quandary. 166 | 167 | 168 | 169 | ### Step 4: Arc plot attempt 170 | 171 | Having extracted the `vertex.names`, it seems that we are ready to plot an arc diagram with the node labels: 172 | 173 | ```{r flo_plot2, eval = FALSE} 174 | # arc plot with node labels 175 | arcplot(flo_edges, labels=flo_names) 176 | ``` 177 | 178 | Well, we are not ready yet. The problem is that we have more labels than nodes in the edge list (node 12 does not appear in `flo\_edges`). The solution is a bit elaborated: first we need to get the node numbers from the edgelist, and then we have to select their corresponding names: 179 | 180 | ```{r flo_labels} 181 | # numeric indices in 'flo_edges' 182 | temp <- unique(as.vector(t(flo_edges))) 183 | temp 184 | 185 | # node labels 186 | flo_labels = attributes(flo_edges)$vnames[temp] 187 | 188 | # check it 189 | flo_labels 190 | ``` 191 | 192 | 193 | ### Step 5: Final plot 194 | 195 | Now we are ready to produce the desired arc diagram: 196 | 197 | ```{r flo_plot3, fig.width=6, fig.height=4, out.width='.9\\linewidth', out.height='.6\\linewidth', fig.align='center', echo=c(1,3)} 198 | # second plot 199 | op = par(mar = c(5, 0, 1, 0)) 200 | arcplot(flo_edges, labels=flo_labels) 201 | par(op) 202 | ``` 203 | 204 | -------------------------------------------------------------------------------- /vignettes/les-miserables.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Les Miserables" 3 | author: "Gaston Sanchez" 4 | output: rmarkdown::html_vignette 5 | vignette: > 6 | %\VignetteIndexEntry{les miserables} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | %\VignetteEncoding{UTF-8} 9 | --- 10 | 11 | ```{r, echo = FALSE, message = FALSE} 12 | knitr::opts_chunk$set(collapse = T, comment = "#>") 13 | library(igraph) 14 | library(arcdiagram) 15 | library(dplyr) 16 | ``` 17 | 18 | ```{r miserables_cover, echo=FALSE, message=FALSE} 19 | # read 'gml' file 20 | mis_file = "../lesmiserables.gml" 21 | mis_graph = read.graph(mis_file, format="gml") 22 | 23 | # get vertex labels 24 | vlabels = get.vertex.attribute(mis_graph, "label") 25 | 26 | # get vertex groups 27 | vgroups = get.vertex.attribute(mis_graph, "group") 28 | 29 | # get vertex fill color 30 | vfill = get.vertex.attribute(mis_graph, "fill") 31 | 32 | # get vertex border color 33 | vborders = get.vertex.attribute(mis_graph, "border") 34 | 35 | # get vertex degree 36 | degrees = degree(mis_graph) 37 | 38 | # get edges value 39 | values = get.edge.attribute(mis_graph, "value") 40 | 41 | # get edgelist 42 | edgelist = get.edgelist(mis_graph) 43 | 44 | # groups and degree 45 | x = data.frame(vgroups, degrees, vlabels, ind=1:vcount(mis_graph)) 46 | y = arrange(x, desc(vgroups), desc(degrees)) 47 | new_ord = y$ind 48 | ``` 49 | 50 | ```{r miser_arcdiag_cover, echo=FALSE, fig.width=13, fig.height=5.5, out.width='1\\linewidth', out.height='.5\\linewidth', fig.align='center'} 51 | # plot 52 | op = par(mar = c(6, 0, 1, 0)) 53 | arcplot(edgelist, ordering=new_ord, labels=vlabels, cex.labels=0.8, 54 | show.nodes=TRUE, col.nodes=vborders, bg.nodes=vfill, 55 | cex.nodes = log(degrees)+0.5, pch.nodes=21, 56 | lwd.nodes = 2, line=-0.5, 57 | col.arcs = hsv(0, 0, 0.2, 0.25), lwd.arcs = 1.5 * values) 58 | par(op) 59 | ``` 60 | 61 | 62 | 63 | ## Introduction 64 | 65 | This document describes the required steps that you'll need to follow to get an arc diagram like the one from _Les Miserables_ with the R package `"arcdiagram"` (a minimalist package designed for plotting pretty arc diagrams). 66 | 67 | 68 | ## Les Miserables 69 | 70 | The file for this example is `lesmiserables.gml` which is available in the github repository of the `"arcdiagram"` package: 71 | 72 | https://github.com/gastonstat/arcdiagram/lesmiserables.gml 73 | 74 | This file is a text file with __GML__ format, which is just a type of format for graphs. You can find more information about GML format at: 75 | 76 | http://en.wikipedia.org/wiki/Graph_Modelling_Language 77 | 78 | 79 | ### Step 1: Read data in R 80 | 81 | I'm assuming that you already checked the introductory documentation of the `"arcdiagram"`. 82 | After downloading the `gml` file, you will have to import it in R using the function `read.graph()` with the argument `format = "gml"`. I assume that the `.gml` file is in your working directory: 83 | 84 | ```{r miserables_file, eval=FALSE} 85 | # load 'arcdiagram' 86 | library(arcdiagram) 87 | 88 | # read 'gml' file 89 | mis_graph = read.graph("lesmiserables.gml", format = "gml") 90 | ``` 91 | 92 | 93 | ### Step 2: Extract edge list 94 | 95 | Since we will use the function `arcplot()`, we need an __edgelist__. The good news is that we can use the function `get.edgelist()` to extract it from `mis_graph`: 96 | 97 | ```{r get_edgelist} 98 | # get edgelist 99 | edgelist = get.edgelist(mis_graph) 100 | ``` 101 | 102 | Once we have the `edgelist`, we can try to get a first ---very raw--- arc diagram with `arcplot()`: 103 | 104 | ```{r miser_plot1, fig.width=10, fig.height=5, out.width='.99\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 105 | # first plot 106 | op = par(mar = c(2, 0.5, 1, 0.5)) 107 | arcplot(edgelist) 108 | par(op) 109 | ``` 110 | 111 | You can see from the previous figure that our first arc diagram has nothing to do with what we are looking for. A better approximation can be obtained if we start tweaking some of the parameters like the symbols of the nodes, the color of the arcs, and their line widths: 112 | 113 | ```{r miser_plot2, fig.width=10, fig.height=5, out.width='.99\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 114 | # second plot 115 | op = par(mar = c(2, 0.5, 1, 0.5)) 116 | arcplot(edgelist, cex.labels=0.8, 117 | show.nodes=TRUE, lwd.nodes = 2, line=-0.5, 118 | col.arcs = hsv(0, 0, 0.2, 0.25), lwd.arcs = 1.5) 119 | par(op) 120 | ``` 121 | 122 | 123 | ### Step 3: Information about nodes and edges 124 | 125 | Most of the necessary ingredients to create our pretty arc diagram are contained in the graph object `mis_graph`: the fill color of the nodes, the border color of the nodes, the group memberships, the node labels, and the arc widths. If you print `mis_graph` you will see the following output: 126 | 127 | ```{r view_mis_graph} 128 | # what's in mis_graph 129 | mis_graph 130 | ``` 131 | 132 | The first line tells you that `mis_graph` is an undirected graph with 77 nodes and 254 edges (`U--- 77 254 --`). The second and third lines indicate that `mis_graph` has the following attributes (`attr`): 133 | 134 | - `id (v/n)`: this is the id of the nodes (numeric) 135 | - `label (v/c)`: this the label of the nodes (character) 136 | - `group (v/n)`: this is the group indicator of nodes (numeric) 137 | - `fill (v/c)`: this is the fill color of the nodes (character) 138 | - `border (v/c)`: this is the border color of the nodes (character) 139 | - `value (e/n)`: this is a value associated to the edges (numeric) 140 | 141 | To extract all the data attributes associated with the nodes in the `mis_graph` we have to use the functions `get.vertex.attribute()` and `get.edge.attribute()`: 142 | 143 | ```{r get_attributes} 144 | # get vertex labels 145 | vlabels = get.vertex.attribute(mis_graph, "label") 146 | 147 | # get vertex groups 148 | vgroups = get.vertex.attribute(mis_graph, "group") 149 | 150 | # get vertex fill color 151 | vfill = get.vertex.attribute(mis_graph, "fill") 152 | 153 | # get vertex border color 154 | vborders = get.vertex.attribute(mis_graph, "border") 155 | 156 | # get edges value 157 | values = get.edge.attribute(mis_graph, "value") 158 | ``` 159 | 160 | In addition to the node (i.e. vertices) attributes, we also need to get the degree of the nodes by using the function `degree()`: 161 | 162 | ```{r get_degree} 163 | # get vertex degree 164 | degrees = degree(mis_graph) 165 | ``` 166 | 167 | ```{r echo=FALSE} 168 | options(width = 60) 169 | ``` 170 | 171 | Ok, let's try a third plot attempt: 172 | 173 | ```{r miser_plot3, fig.width=10, fig.height=5, out.width='.99\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 174 | # third plot 175 | op = par(mar = c(5, 0, 1, 0)) 176 | arcplot(edgelist, labels=vlabels, cex.labels=0.8, 177 | show.nodes=TRUE, col.nodes=vborders, bg.nodes=vfill, 178 | cex.nodes = log(degrees)+0.5, pch.nodes=21, 179 | lwd.nodes = 2, line=-0.5, 180 | col.arcs = hsv(0, 0, 0.2, 0.25), lwd.arcs = 1.5 * values) 181 | par(op) 182 | ``` 183 | 184 | 185 | ### Step 4: Nodes Ordering 186 | 187 | We are very close to our objective but we still need the right ordering for the nodes. One option to get the nodes ordering is by using the package `dplyr` (by Hadley Wickham): 188 | 189 | ```{r dplyr, eval=FALSE} 190 | # if you haven't installed it 191 | install.packages("dplyr") 192 | 193 | # load 'dplyr' 194 | library(dplyr) 195 | ``` 196 | 197 | The idea is to create a data frame with the following variables: `vgroups`, `degrees`, `vlabels`, and a numeric index for the nodes `ind`. 198 | 199 | ```{r data_frame} 200 | # data frame with node attributes 201 | x = data.frame(vgroups, degrees, vlabels, ind=1:vcount(mis_graph)) 202 | 203 | # take a peek to the data frame 204 | head(x) 205 | ``` 206 | 207 | We will arrange the data frame in descending order, first by `vgroups` and then by `degrees`; what we want is the sorted `ind`: 208 | 209 | ```{r ordering} 210 | # arrange by groups and degree 211 | y = arrange(x, desc(vgroups), desc(degrees)) 212 | 213 | # what does 'y' look like? 214 | head(y) 215 | 216 | # get 'ind' ordering 217 | new_ord = y$ind 218 | ``` 219 | 220 | 221 | ### Step 5: Final plot 222 | 223 | Now we are ready to produce the desired arc diagram: 224 | 225 | ```{r miser_arcdiag_plot, fig.width=10, fig.height=5, out.width='.99\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 226 | # plot 227 | op = par(mar = c(6, 0, 1, 0)) 228 | arcplot(edgelist, ordering=new_ord, labels=vlabels, cex.labels=0.8, 229 | show.nodes=TRUE, col.nodes=vborders, bg.nodes=vfill, 230 | cex.nodes = log(degrees)+0.5, pch.nodes=21, 231 | lwd.nodes = 2, line=0, 232 | col.arcs = hsv(0, 0, 0.2, 0.25), lwd.arcs = 1.5 * values) 233 | par(op) 234 | ``` 235 | 236 | -------------------------------------------------------------------------------- /vignettes/introduction.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to arcdiagram" 3 | author: "Gaston Sanchez" 4 | output: rmarkdown::html_vignette 5 | vignette: > 6 | %\VignetteIndexEntry{Introduction to arcdiagram} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | %\VignetteEncoding{UTF-8} 9 | --- 10 | 11 | ```{r, echo = FALSE, message = FALSE} 12 | knitr::opts_chunk$set(collapse = T, comment = "#>") 13 | library(igraph) 14 | library(arcdiagram) 15 | ``` 16 | 17 | `"arcdiagram"` is a minimalist R package designed for the solely purpose of helping you plot pretty arc diagrams like the one below: 18 | 19 | ```{r arcdiag_cover, echo=FALSE, message=FALSE, fig.width=5, fig.height=4, out.width='.9\\linewidth', out.height='.6\\linewidth', fig.align='center'} 20 | library(arcdiagram) 21 | 22 | # ggplot colors 23 | ggcols <- function(n, alfa) { 24 | hues = seq(15,375,length=n+1) 25 | hcl(h=hues, l=65, c=100, alpha=alfa)[1:n] 26 | } 27 | 28 | # tree graph example 29 | covergraph = graph.full(n=8) 30 | V(covergraph)$name = toupper(letters[1:vcount(covergraph)]) 31 | cover_edges = get.edgelist(covergraph) 32 | 33 | # plot 34 | op = par(mar = c(1,1,1,1)) 35 | set.seed(325) 36 | arcplot(cover_edges, lwd.arcs=runif(28,1,8), col.arcs=ggcols(10, 0.5)[7:10], 37 | show.nodes=TRUE, cex.nodes=1.5, col.nodes="gray90", las=1, line=-0.5) 38 | par(op) 39 | ``` 40 | 41 | 42 | ## Arc Diagrams 43 | 44 | So, what is an arc diagram? Briefly, an __arc diagram__ is a graphical display to visualize graphs or networks in a _one-dimensional layout_. The main idea is to display nodes along a single axis, while representing the edges or connections between nodes with arcs. 45 | 46 | The reason why an arc diagram is said to be a one-dimensional layout is because all the nodes lay on one axis, as opposed to other more common visualizations of graphs where nodes are spreaded in a two-dimensional space (see the following figure): 47 | 48 | ```{r arc_diag_example, echo=FALSE, fig.width=7, fig.height=3.5, out.width='.9\\linewidth', out.height='.4\\linewidth', fig.align='center'} 49 | # graph 50 | tree_graph = graph.tree(5, 2) 51 | V(tree_graph)$name = paste("Node", 1:vcount(tree_graph), sep='') 52 | tree_edges = get.edgelist(tree_graph) 53 | # plot 54 | op = par(mfrow = c(1,2), mar = c(2,1,3,1)) 55 | plot(tree_graph) 56 | title("Typical Graph\n(two-dimensional)", col.main="gray50", cex.main=0.9) 57 | arcplot(tree_edges, labels=V(tree_graph)$name, las=1) 58 | title("Arc Diagram\n(one-dimensional)", col.main="gray50", cex.main=0.9) 59 | par(op) 60 | ``` 61 | 62 | One of the disadvantages of arc diagrams is that they are sensitive to node ordering; ideally, better visualizations are achieved when related nodes are close to each other, which helps us detect clusters or groups of nodes. 63 | 64 | Often, a random node ordering produces poor diagrams in which large arcs have crossovers that difficult visual processing. From the practical point of view, the ordering issue will force you to play with different settings until you find one that allows you to get good results. 65 | 66 | Some network specialists acknowledge that arc diagrams might be appropriate for undirected graphs, making them useful for annotations as compared to other two-dimensional network layouts, such as rollup, matrix or table layouts. 67 | 68 | 69 | 70 | ## The R package `arcdiagram` 71 | 72 | `"arcdiagram"` is a minimal package for plotting basic arc diagrams in R. My main motivation for creating `arcdiagram` was because of __Similar Diversity__, a really nice graphic design project by Philipp Steinweber and Andreas Koller [href{http://similardiversity.net/](http://similardiversity.net/). Being deeply captivated with such an amazing visualization I decided to do a more modest attempt in R which indirectly took me to the development of `arcdiagram`. 73 | 74 | 75 | ## Installation 76 | 77 | `"ardiagram"` is not available on CRAN; instead it lives in one of my github repositories: 78 | 79 | https://github.com/gastonstat/arcdiagram 80 | 81 | This means that you have to use the package `"devtools"` (by Hadley Wickham) in order to install `arcdiagram` in R: 82 | 83 | ```{r github, message=FALSE, eval=FALSE} 84 | # install 'devtools' if you haven't 85 | install.packages("devtools") 86 | 87 | # load devtools 88 | library(devtools) 89 | 90 | # then download 'arcdiagram' using 'install_github' 91 | install_github('arcdiagram', username='gastonstat') 92 | 93 | # load arcdiagram 94 | library(arcdiagram) 95 | ``` 96 | 97 | 98 | ## Basic Usage 99 | 100 | Because the only purpose behind `"arcdiagram"` is to visualize graphs (i.e. networks), I designed it having in mind the package `"igraph"` (by Gabor Csardi and Tamas Nepusz). In other words, I developed `"arcdiagram"` as a _plugin_ of `"igraph"`. The structure of the package is very simple and it consists of one main function: `arcplot()`; and one accesory function: `xynodes()`. 101 | 102 | The way `arcplot()` works is very simple: it takes an object `"edgelist"` and it plots the edges as arcs. If you are not familiar with this term, an __edge list__ is just a two column matrix that gives the list of edges for a graph. Let's see an example: 103 | 104 | ```{r dummy_graph, eval=FALSE} 105 | # create a graph with 8 nodes 106 | star_graph = graph.star(8, mode="out") 107 | 108 | # add names to nodes 109 | V(star_graph)$name = paste("node", 1:vcount(star_graph), sep="-") 110 | 111 | # extract edgelist 112 | star_edges = get.edgelist(star_graph) 113 | 114 | # plot arc diagram 115 | arcplot(star_edges, las=1) 116 | ``` 117 | 118 | ```{r arcplot_dummy_graph, fig.width=7, fig.height=4, out.width='.9\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=FALSE} 119 | # create a graph with 10 nodes 120 | star_graph = graph.star(8, mode="out") 121 | 122 | # add names to nodes 123 | V(star_graph)$name = paste("node", 1:vcount(star_graph), sep="-") 124 | 125 | # extract edgelist 126 | star_edges = get.edgelist(star_graph) 127 | 128 | #plot 129 | op = par(mar = c(4, 0.5, 0.5, 0.5)) 130 | arcplot(star_edges, las=1, lwd.arcs=2) 131 | par(op) 132 | ``` 133 | 134 | 135 | ### Function `arcplot()` 136 | 137 | If you check the documentation of the function `arcplot()` you'll see that there's a bunch of parameters to play with. The main parameter is the `edgelist` which is a two-column matrix with the edges of the graph. This is the mandatory ingredient that you have to provide. The rest of parameters are either optional or have default values. However, if you want to spark your creativity with `arcplot()` we need to talk about the elements present in an arc diagram. 138 | 139 | Basically we have three elements: 1) the nodes (or vertices), 2) the arcs (or edges), and 3) the node labels. The nodes and the labels are optional (you can choose whether to show them). 140 | 141 | 142 | ### Arcs arguments 143 | 144 | The arcs are plotted by `arcplot()` using the `lines()` function internally. This means that the arc-related arguments are basically the arguments behind `lines()`: 145 | 146 | - `col.arcs`: color for the arcs 147 | - `lwd.arcs`: line width for the arcs (default 1) 148 | - `lty.arcs`: line type for the arcs 149 | - `lend`: the line end style for the arcs 150 | - `ljoin`: the line join style for the arcs 151 | - `lmitre`: the line mitre limit for the arcs 152 | 153 | __Node symbols' arguments.__ 154 | Node symbols are plotted by `arcplot()` using the `points()` function internally. What this means is that the node symbols arguments are basically the arguments that `points()` uses: 155 | 156 | - `show.nodes`: logical indicating whether to show node symbols 157 | - `pch.nodes`: symbol to use when plotting nodes 158 | - `cex.nodes`: expansion of the node symbols 159 | - `col.nodes`: color of the node symbols 160 | - `bg.nodes`: background (fill) color for the node symbols given by `pch.nodes=21:25` 161 | - `lwd.nodes`: line width for drawing node symbols 162 | 163 | __Node labels' arguments.__ 164 | In turn, node labels are plotted by `arcplot()` using the `mtext()` function internally. Node labels' arguments are related to the arguments behind `mtext()`: 165 | 166 | - `show.labels`: logical indicating whether to show node labels 167 | - `labels`: character vector with labels for the nodes 168 | - `col.labels`: color of the node labels 169 | - `cex.labels`: expansion of node labels 170 | - `las`: numeric in {0,1,2,3}; the style of axis labels 171 | - `font`: font used for node labels 172 | - `line`: on which margin line the node labels are displayed 173 | - `outer`: use outer margins, if available, to plot node labels 174 | - `adj`: adjustment for each string in reading direction 175 | - `padj`: adjustment for each string perpendicular to the reading direction 176 | 177 | 178 | ### Additional arguments 179 | 180 | In addition to the previous arguments, there's a handful of additional parameters in `arcplot()` that control the ordering of the nodes and the layout orientation: 181 | 182 | - `sorted`: logical to indicate if nodes should be sorted 183 | - `decreasing`: logical to indicate type of sorting 184 | - `ordering`: optional numeric vector providing the ordering of nodes 185 | - `horizontal`: logical indicating whether to plot in horizontal orientation 186 | 187 | 188 | ## Examples 189 | 190 | Let's see a basic example. We will manually create an `edgelist` representing a graph of projects between coworkers in a scientific laboratory: 191 | 192 | ```{r lab_edgelist, tidy=FALSE} 193 | # create an edgelist 194 | lab <- rbind( 195 | c("Emilia", "Kirk"), 196 | c("Emilia", "Yong"), 197 | c("Filipe", "Matteo"), 198 | c("Filipe", "Tyler"), 199 | c("Matteo", "Filipe"), 200 | c("Matteo", "Tyler"), 201 | c("Mehmet", "Rori"), 202 | c("Rori", "Kirk"), 203 | c("Rori", "Vitor"), 204 | c("Anna", "Mehmet"), 205 | c("Anna", "Yong") 206 | ) 207 | ``` 208 | 209 | 210 | Once we created our `edgelist`, we can create an arc diagram with `arcplot()`: 211 | 212 | ```{r lab_arcplot_ex1, fig.width=7, fig.height=4, out.width='.9\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 213 | # arc diagram 214 | op = par(mar = c(3,0.5,0.5,0.5)) 215 | arcplot(lab) 216 | par(op) 217 | ``` 218 | 219 | 220 | If you want to inspect how the `edgelist` looks like, simply type: 221 | 222 | ```{r inspect_lab} 223 | # how does it look like 224 | lab 225 | ``` 226 | 227 | 228 | ### Creating a graph 229 | 230 | If we want to plot our graph using the package `igraph()`, first we need to create a `"graph"` object with the function `graph.edgelist()`, and then we can use the default `plot()` method: 231 | 232 | ```{r lab_graph, fig.width=6, fig.height=4, out.width='.9\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,2,4,6)} 233 | # make graph from edgelist 234 | glab = graph.edgelist(lab, directed=TRUE) 235 | 236 | # plot graph 237 | op = par(mar = c(0.5, 0.5, 0.5, 0.5)) 238 | plot(glab) 239 | par(op) 240 | ``` 241 | 242 | 243 | ## Playing with arc diagrams 244 | 245 | The first arc diagram that we produced is not bad but we can definitely improve it. For instance, we can take into account nodes' degree---the __degree__ of a node is the number of edges connected to it---using the function `degree()`: 246 | 247 | ```{r lab_degree} 248 | # degrees 249 | lab_degree = degree(glab) 250 | ``` 251 | 252 | 253 | Let's say that we want to put weights on the edges so they reflect some sort of value. We can do this by assigning some random numbers: 254 | 255 | ```{r lab_weights} 256 | # assign random weights to edges 257 | set.seed(123) 258 | E(glab)$weight = round(runif(nrow(lab), .5, 4)) 259 | ``` 260 | 261 | 262 | We can also get clusters of the nodes using the function `clusters()`: 263 | 264 | ```{r lab_clusters} 265 | # get clusters 266 | gclus = clusters(glab) 267 | ``` 268 | 269 | 270 | To make our arc diagram more appealing, we need some colors reflecting the cluster memberships: 271 | 272 | ```{r lab_cluster_colors} 273 | # define two hues of blue 274 | blues = c("#adccff","#4272bf") 275 | 276 | # vector of colors based on cluster membership 277 | cols = blues[gclus$membership] 278 | ``` 279 | 280 | ```{r echo=FALSE} 281 | options(width = 60) 282 | ``` 283 | 284 | 285 | Now that we have all the necessary ingredients, we apply `arcplot()`: 286 | 287 | ```{r lab_arcdiagram_ex2, fig.width=6, fig.height=4, out.width='.9\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 288 | # another arc diagram 289 | op = par(mar = c(4, 0.5, 1, 0.5)) 290 | arcplot(lab, lwd.arcs = 2*E(glab)$weight, 291 | cex.nodes=lab_degree, col.nodes=cols, bg.nodes=cols, 292 | show.nodes=TRUE) 293 | par(op) 294 | ``` 295 | 296 | 297 | Let's change the colors of the arcs: 298 | 299 | ```{r lab_arcdiagram_ex3, fig.width=6, fig.height=4, out.width='.9\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 300 | # another arc diagram 301 | op = par(mar = c(4, 0.5, 1, 0.5)) 302 | arcplot(lab, lwd.arcs = 2*E(glab)$weight, col.arcs = "#77777765", 303 | cex.nodes=lab_degree, col.nodes=cols, bg.nodes=cols, 304 | show.nodes=TRUE) 305 | par(op) 306 | ``` 307 | 308 | 309 | Let's order the nodes according to the clusters: 310 | 311 | ```{r lab_arcdiagram_ex4, fig.width=6, fig.height=4, out.width='.9\\linewidth', out.height='.5\\linewidth', fig.align='center', echo=c(1,3)} 312 | # another arc diagram 313 | op = par(mar = c(4, 0.5, 1, 0.5)) 314 | arcplot(lab, lwd.arcs = 2*E(glab)$weight, col.arcs = "#77777765", 315 | cex.nodes=lab_degree, col.nodes=cols, bg.nodes=cols, 316 | show.nodes=TRUE, ordering=order(gclus$membership)) 317 | par(op) 318 | ``` 319 | 320 | 321 | Let's change the diagram to a vertical orientation 322 | 323 | ```{r lab_arcdiagram_ex5, fig.width=4, fig.height=6, out.width='.65\\linewidth', out.height='.65\\linewidth', fig.align='center', echo=c(1,3)} 324 | # arc diagram in vertical orientation 325 | op = par(mar = c(0.5, 7, 0.5, 3)) 326 | arcplot(lab, lwd.arcs = 2*E(glab)$weight, col.arcs = "#77777765", 327 | cex.nodes=lab_degree, col.nodes=cols, bg.nodes=cols, 328 | show.nodes=TRUE, ordering=order(gclus$membership), 329 | horizontal=FALSE) 330 | par(op) 331 | ``` 332 | 333 | 334 | 335 | ### Some References 336 | 337 | - Arc Diagrams in _Visual Complexity_ (by Manuel Lima) 338 | http://www.visualcomplexity.com/vc/index.cfm?method=Arc\%20Diagrams 339 | 340 | - Protovis by Mike Bostock 341 | http://mbostock.github.com/protovis/ex/arc.html 342 | 343 | - Arc Diagrams: Visualizing Structure in Strings by Martin Wattenberg 344 | http://hint.fm/papers/arc-diagrams.pdf 345 | 346 | - R-chie: A web server and R package for plotting arc diagrams of RNA secondary structures (by Daniel Lai, Jeff R. Proctor, Jing Yun A. Zhu, and Irmtraud M. Meyer) 347 | http://www.e-rna.org/r-chie/index.cgi 348 | -------------------------------------------------------------------------------- /R/arcplot.r: -------------------------------------------------------------------------------- 1 | #' @title Graph Information 2 | #' 3 | #' @description Gets graph information 4 | #' 5 | #' @param edgelist basically a two-column matrix with edges 6 | #' (see \code{\link{graph}}) 7 | #' @param vertices optional vector of vertex names corresponding with 8 | #' those in the edgelist 9 | #' @param sorted logical to indicate if nodes should be sorted 10 | #' (default \code{FALSE}) 11 | #' @param decreasing logical to indicate type of sorting 12 | #' (used only when \code{sorted=TRUE}) 13 | #' @param ordering optional numeric or string vector providing the 14 | #' ordering of nodes. When provided, this parameter overrides 15 | #' \code{sorted=TRUE}). See the details section for more information. 16 | #' @param labels optional string vector with labels for the nodes 17 | #' @export 18 | #' @keywords internal 19 | graph_info <- 20 | function(edgelist, vertices, sorted = FALSE, decreasing = FALSE, 21 | ordering = NULL, labels = NULL) 22 | { 23 | # ====================================================== 24 | # Checking arguments 25 | # ====================================================== 26 | # edgelist as a two-column matrix 27 | if (!is.matrix(edgelist) || ncol(edgelist) != 2) 28 | stop("\nSorry, 'edgelist' must be a two column matrix") 29 | 30 | num_edges = nrow(edgelist) 31 | # get nodes (this could be numeric or character) 32 | if(hasArg(vertices)){ 33 | #to deal with singleton nodes 34 | nodes = vertices 35 | }else{ 36 | nodes = unique(as.vector(t(edgelist))) 37 | } 38 | num_nodes = length(nodes) 39 | # check labels (i.e. node names) 40 | if (!is.null(labels)) 41 | { 42 | if (length(labels) != num_nodes) 43 | stop("\nLength of 'labels' differs from number of nodes") 44 | } else { 45 | labels = nodes 46 | } 47 | 48 | # auxiliar order (this may change if sorted or ordering required) 49 | aux_ord = 1:num_nodes 50 | 51 | # If sorted is required, ennumerate nodes 52 | if (sorted) { 53 | ordered_nodes = order(nodes, decreasing = decreasing) 54 | nodes = nodes[ordered_nodes] 55 | labels = labels[ordered_nodes] 56 | # auxiliar order 57 | aux_ord = ordered_nodes 58 | } 59 | 60 | # If ordering is provided, re-ennumerate nodes 61 | if (!is.null(ordering)) 62 | { 63 | if (length(ordering) != num_nodes) { 64 | stop("\nLength of 'ordering' differs from number of nodes") 65 | } 66 | 67 | if (is.character(ordering)) { 68 | # make sure labels contains elements in ordering 69 | unmatched_ordering <- !(ordering %in% labels) 70 | if (any(unmatched_ordering)) { 71 | undetected = ordering[unmatched_ordering] 72 | stop(sprintf("\nUnrecognized values in ordering: '%s'", undetected)) 73 | } 74 | ordering = match(ordering, labels) 75 | } 76 | 77 | nodes = nodes[ordering] 78 | labels = labels[ordering] 79 | # auxiliar order 80 | aux_ord = ordering 81 | } 82 | 83 | ## output 84 | list( 85 | nodes = nodes, 86 | labels = labels, 87 | num_nodes = num_nodes, 88 | num_edges = num_edges, 89 | aux_ord = aux_ord 90 | ) 91 | } 92 | 93 | 94 | #' @title X or Y coordinates of node locations 95 | #' 96 | #' @description 97 | #' Gives axis locations of each node 98 | #' 99 | #' @param num_nodes number of nodes 100 | #' @param aux_ord vector with the index number for ordering the nodes 101 | #' @param labels optional string vector with labels for the nodes 102 | #' @export 103 | xynodes <- function(num_nodes, aux_ord, labels) 104 | { 105 | # ====================================================== 106 | # Coordinates of nodes (i.e. vertices) 107 | # ====================================================== 108 | # node labels at equal distances from each other 109 | nf = rep(1 / num_nodes, num_nodes) 110 | # center coordinates of node labels 111 | fin = cumsum(nf) 112 | ini = c(0, cumsum(nf)[-num_nodes]) 113 | centers = (ini + fin) / 2 114 | names(centers) = labels[aux_ord] 115 | 116 | # output 117 | centers 118 | } 119 | 120 | 121 | #' @title Arc Radius Locations 122 | #' 123 | #' @description Computes the location and radius of each arc 124 | #' 125 | #' @param edgelist 2-column matrix 126 | #' @param nodes vector of nodes 127 | #' @param centers vector with xy-positions of nodes 128 | #' @return a list with locations and radios 129 | #' @return \item{locs}{locations} 130 | #' @return \item{radios}{radius values} 131 | #' @export 132 | #' @keywords internal 133 | arc_radius_locs <- function(edgelist, nodes, centers) 134 | { 135 | # ====================================================== 136 | # Coordinates of arcs (i.e. edges) 137 | # ====================================================== 138 | # handy matrix with numeric indices '1:FROM' , '2:TO' 139 | edges_from_to = matrix(0, nrow(edgelist), 2) 140 | for (i in 1L:nrow(edgelist)) 141 | { 142 | edges_from_to[i,1] = centers[which(nodes == edgelist[i,1])] 143 | edges_from_to[i,2] = centers[which(nodes == edgelist[i,2])] 144 | } 145 | 146 | # maximum radius of arcs 147 | radios = abs(edges_from_to[,1] - edges_from_to[,2]) / 2 148 | max_radios = which(radios == max(radios)) 149 | max_rad = unique(radios[max_radios] / 2) 150 | 151 | # arc locations 152 | locs = rowSums(edges_from_to) / 2 153 | 154 | # output 155 | list(locs = locs, radios = radios) 156 | } 157 | 158 | 159 | #' @title Above or Below 160 | #' 161 | #' @description Determines how arcs should be displayed 162 | #' @details 163 | #' If \code{horizontal = TRUE} then arcs can be plotted above or 164 | #' below the horizontal axis \cr 165 | #' If \code{horizontal = FALSE} then arcs can be plotted to the right or 166 | #' left of the vertical axis 167 | #' @param edgelist two-column matrix 168 | #' @param above optional numeric or logical vector indicating what edges 169 | #' (arcs) should be plotted above (or to the right of) of chosen axis 170 | #' If \code{above = NULL} then all arcs are plotted above (or to the right) 171 | #' If \code{above} is numeric, it cannot contain both positive and negative 172 | #' indices. 173 | #' If \code{above} is logical, its length must equal the number of rows in 174 | #' \code{edgelist} 175 | #' @return a logical vector indicating how arcs should be displayed 176 | #' @export 177 | #' @keywords internal 178 | above_below <- function(edgelist, above) 179 | { 180 | # ====================================================== 181 | # Coordinates of arcs (i.e. edges) below the axis 182 | # ====================================================== 183 | # check above 184 | if (is.null(above)) { 185 | above = rep(TRUE, nrow(edgelist)) 186 | } else { 187 | if (length(above) > nrow(edgelist)) 188 | stop("\nlength of 'above' exceeds number of rows in 'edgelist'") 189 | # check numeric above and convert to logical 190 | if (is.numeric(above)) { 191 | above_positive <- any(above > 0) 192 | above_negative <- any(above < 0) 193 | if (above_positive & above_negative) 194 | stop("\n'above' cannot contain both negative and positive indices") 195 | # convert to logical 196 | if (all(above > 0)) { 197 | above = 1:nrow(edgelist) %in% above 198 | } 199 | if (all(above < 0)) { 200 | above <- !(-(1:nrow(edgelist)) %in% above) 201 | } 202 | if (all(above == 0)) { 203 | above = rep(FALSE, nrow(edgelist)) 204 | } 205 | } 206 | # check logical above 207 | if (is.logical(above)) { 208 | if (length(above) != nrow(edgelist)) 209 | stop("\nlength of 'above' must equal number of rows in 'edgelist'") 210 | } 211 | } 212 | 213 | # output 214 | above 215 | } 216 | 217 | 218 | #' @title Minimum and Maximum Margin Limits 219 | #' @description Computes the minimum and maximum margin limits of 220 | #' plotting region 221 | #' @param radios vector of arc radius 222 | #' @param above logical vectors indicating whether arcs should be displayed 223 | #' @return list with minimum and maximum margin limits 224 | #' @export 225 | #' @keywords internal 226 | min_max_margin <- function(radios, above) 227 | { 228 | # determine maximum radius 229 | max_radios = which(radios == max(radios)) 230 | 231 | # minimum and maximum margin limits 232 | lim_min = 0 233 | lim_max = 0 234 | 235 | above_radios = radios[above] 236 | if (length(above_radios > 0)) { 237 | max_above_radios = which(above_radios == max(above_radios))[1] 238 | lim_max = above_radios[max_above_radios] 239 | } 240 | 241 | below_radios = radios[!above] 242 | if (length(below_radios > 0)) { 243 | max_below_radios = which(below_radios == max(below_radios))[1] 244 | lim_min = -1 * below_radios[max_below_radios] 245 | } 246 | 247 | # margin limits 248 | list(min = lim_min, max = lim_max) 249 | } 250 | 251 | 252 | 253 | 254 | #' @title Arc Diagram Plot 255 | #' 256 | #' @description 257 | #' Give me an edgelist and I'll help you plot a pretty damn arc diagram 258 | #' 259 | #' @details 260 | #' The arcs are scaled such that they fit in a plot region with its 261 | #' x-axis ranging from zero to one. Node symbols and labels can be 262 | #' optionally displayed. Node symbols are displayed through 263 | #' the function \code{points}. In turn, node labels are displayed 264 | #' through the function \code{mtext}. 265 | #' 266 | #' When \code{ordering} is provided in numeric format and node labels are 267 | #' strings, the labels are alphabetically ordered first, and then nodes are 268 | #' sorted according to the provided \code{ordering}. 269 | #' 270 | #' If \code{ordering} is provided in string format, the node labels must be 271 | #' strings as well. The nodes will be sorted according to \code{ordering}. 272 | #' 273 | #' @param edgelist basically a two-column matrix with edges 274 | #' (see \code{\link{graph}}) 275 | #' @param vertices optional vector of vertex names corresponding with 276 | #' those in the edgelist 277 | #' @param sorted logical to indicate if nodes should be sorted 278 | #' (default \code{FALSE}) 279 | #' @param decreasing logical to indicate type of sorting 280 | #' (used only when \code{sorted=TRUE}) 281 | #' @param ordering optional numeric or string vector providing the 282 | #' ordering of nodes. When provided, this parameter overrides 283 | #' \code{sorted=TRUE}). See the details section for more information. 284 | #' @param labels optional string vector with labels for the nodes 285 | #' @param horizontal logical indicating whether to plot 286 | #' in horizontal orientation 287 | #' @param above optional vector indicating which arcs should be displayed 288 | #' above (or to the right) and below (or to the left) of the axis 289 | #' @param col.arcs color for the arcs (default \code{"gray50"}) 290 | #' @param lwd.arcs line width for the arcs (default 1) 291 | #' @param lty.arcs line type for the arcs (see \code{\link{par}}) 292 | #' @param lend the line end style for the arcs (see \code{\link{par}}) 293 | #' @param ljoin the line join style for the arcs (see \code{\link{par}}) 294 | #' @param lmitre the line mitre limit for the arcs (see \code{\link{par}}) 295 | #' @param show.nodes logical indicating whether to show node symbols 296 | #' @param pch.nodes plotting 'character', i.e. symbol to use when 297 | #' plotting nodes (\code{pch.nodes=0:25}) 298 | #' @param cex.nodes expansion of the node symbols (default 1) 299 | #' @param col.nodes color of the node symbols (default \code{"gray50"}) 300 | #' @param bg.nodes background (fill) color for the node symbols 301 | #' given by \code{pch.nodes=21:25} 302 | #' @param lwd.nodes line width for drawing node symbols 303 | #' (see \code{\link{points}}) 304 | #' @param show.labels logical indicating whether to show node labels 305 | #' @param col.labels color of the node labels (default \code{"gray50"}) 306 | #' @param cex.labels expansion of node labels (default \code{"gray50"}) 307 | #' @param las numeric in {0,1,2,3}; the style of axis labels 308 | #' (see \code{\link{par}}) 309 | #' @param font font used for node labels (see \code{\link{par}}) 310 | #' @param line on which margin line the node labels are displayed, 311 | #' starting at 0 counting outwards (see \code{\link{mtext}}) 312 | #' @param outer use outer margins, if available, to plot node labels 313 | #' (see \code{\link{mtext}}) 314 | #' @param adj adjustment for each string in reading direction 315 | #' (see \code{\link{mtext}}) 316 | #' @param padj adjustment for each string perpendicular to 317 | #' the reading direction (see \code{\link{mtext}}) 318 | #' @param axes logical indicating whether to plot the axes 319 | #' (default \code{FALSE}) 320 | #' @param xlim numeric vector of length 2, giving the x coordinates 321 | #' @param ylim numeric vector of length 2, giving the y coordinates 322 | #' @param ... further graphical parameters (see \code{\link{par}}), including 323 | #' \code{family}, \code{xpd}, \code{main}, \code{asp}, etc. 324 | #' @author Gaston Sanchez 325 | #' @seealso \code{\link{xynodes}} 326 | #' @export 327 | #' @examples 328 | #' 329 | #' \dontrun{ 330 | #' # create an edgelist 331 | #' un_graphe <- rbind( 332 | #' c("fromage", "pain"), 333 | #' c("pain", "vin"), 334 | #' c("vin", "biere"), 335 | #' c("cidre", "biere"), 336 | #' c("foie", "fromage"), 337 | #' c("pain", "foie")) 338 | #' 339 | #' # deafult arcplot 340 | #' arcplot(un_graphe) 341 | #' # vertical display 342 | #' arcplot(un_graphe, horizontal=FALSE) 343 | #' # arcplot with arcs above and below axis 344 | #' arcplot(un_graphe, above = c(1, 3, 5)) 345 | #' # nodes sorted alphabetically (increasing) 346 | #' arcplot(un_graphe, sorted=TRUE) 347 | #' # nodes sorted alphabetically (decreasing) 348 | #' arcplot(un_graphe, sorted=TRUE, decreasing = TRUE) 349 | #' # provided order for nodes 350 | #' new_order = c("vin", "biere", "cidre", "fromage", "foie", "pain") 351 | #' arcplot(un_graphe, ordering = new_order) 352 | #' 353 | #' 354 | #' # generate graphs 355 | #' ring_graph = graph.ring(10) 356 | #' star_graph = graph.star(10, mode="out") 357 | #' tree_graph = graph.tree(10, 2) 358 | #' 359 | #' # add names to nodes 360 | #' V(ring_graph)$name = letters[1:vcount(ring_graph)] 361 | #' V(star_graph)$name = paste("Node", 1:vcount(star_graph)) 362 | #' V(tree_graph)$name = paste("V", 1:vcount(tree_graph), sep='') 363 | #' 364 | #' # extract edgelist 365 | #' ring_edges = get.edgelist(ring_graph) 366 | #' star_edges = get.edgelist(star_graph) 367 | #' tree_edges = get.edgelist(tree_graph) 368 | #' 369 | #' # arc diagram 370 | #' arcplot(ring_edges, labels=V(ring_graph)$name, las=1) 371 | #' arcplot(star_edges, labels=V(star_graph)$name, las=2) 372 | #' arcplot(tree_edges, labels=V(tree_graph)$name, las=2) 373 | #' 374 | #' # compare to plot.igraph 375 | #' plot(ring_graph, vertex.label=V(ring_graph)$name) 376 | #' plot(star_graph, vertex.label=V(star_graph)$name) 377 | #' plot(tree_graph, vertex.label=V(tree_graph)$name) 378 | #' } 379 | #' 380 | arcplot <- function( 381 | edgelist, vertices, sorted = FALSE, decreasing = FALSE, ordering = NULL, 382 | labels = NULL, horizontal = TRUE, above = NULL, 383 | col.arcs = "#5998ff77", lwd.arcs = 1.8, lty.arcs = 1, 384 | lend = 1, ljoin = 2, lmitre = 1, show.nodes = TRUE, pch.nodes = 19, 385 | cex.nodes = 1, col.nodes = "gray80", bg.nodes = "gray80", lwd.nodes = 1, 386 | show.labels = TRUE, col.labels = "gray55", 387 | cex.labels = 0.9, las = 2, font = 1, line = 0, 388 | outer = FALSE, adj = NA, padj = NA, axes = FALSE, xlim = NULL, ylim = NULL, ...) 389 | { 390 | # Get graph information 391 | if (hasArg(vertices)) { 392 | nodes_edges = graph_info(edgelist, vertices = vertices, sorted = sorted, 393 | decreasing = decreasing, 394 | ordering = ordering, labels = labels) 395 | } else { 396 | nodes_edges = graph_info(edgelist, sorted = sorted, decreasing = decreasing, 397 | ordering = ordering, labels = labels) 398 | } 399 | nodes = nodes_edges$nodes 400 | num_nodes = nodes_edges$num_nodes 401 | num_edges = nodes_edges$num_edges 402 | aux_ord = nodes_edges$aux_ord 403 | labels = nodes_edges$labels 404 | 405 | # x-y node coordinates 406 | centers = xynodes(num_nodes, aux_ord, labels) 407 | 408 | # determine above or below display of arcs 409 | above = above_below(edgelist, above) 410 | 411 | # arc radius and locations 412 | radios_locs = arc_radius_locs(edgelist, nodes, centers) 413 | radios = radios_locs$radios 414 | locs = radios_locs$locs 415 | 416 | # ====================================================== 417 | # Graphical parameters for Arcs 418 | # ====================================================== 419 | # color of arcs 420 | if (length(col.arcs) != num_edges) 421 | col.arcs = rep(col.arcs, length=num_edges) 422 | # line width of arcs 423 | if (length(lwd.arcs) != num_edges) 424 | lwd.arcs = rep(lwd.arcs, length=num_edges) 425 | # line type of arcs 426 | if (length(lty.arcs) != num_edges) 427 | lty.arcs = rep(lty.arcs, length=num_edges) 428 | 429 | # ====================================================== 430 | # Graphical parameters for Nodes 431 | # ====================================================== 432 | # pch symbol of nodes 433 | if (length(pch.nodes) != num_nodes) { 434 | pch.nodes = rep(pch.nodes, length = num_nodes) 435 | } 436 | pch.nodes = pch.nodes[aux_ord] 437 | # cex of nodes 438 | if (length(cex.nodes) != num_nodes) { 439 | cex.nodes = rep(cex.nodes, length = num_nodes) 440 | } 441 | cex.nodes = cex.nodes[aux_ord] 442 | # color of nodes 443 | if (length(col.nodes) != num_nodes) { 444 | col.nodes = rep(col.nodes, length = num_nodes) 445 | } 446 | col.nodes = col.nodes[aux_ord] 447 | # bg of nodes 448 | if (length(bg.nodes) != num_nodes) { 449 | bg.nodes = rep(bg.nodes, length = num_nodes) 450 | } 451 | bg.nodes = bg.nodes[aux_ord] 452 | # line widths of nodes 453 | if (length(lwd.nodes) != num_nodes) { 454 | lwd.nodes = rep(lwd.nodes, length = num_nodes) 455 | } 456 | lwd.nodes = lwd.nodes[aux_ord] 457 | 458 | # ====================================================== 459 | # Graphical parameters for Node Labels 460 | # ====================================================== 461 | # color of labels 462 | if (length(col.labels) != num_nodes) { 463 | col.labels = rep(col.labels, length = num_nodes) 464 | } 465 | col.labels = col.labels[aux_ord] 466 | # cex of labels 467 | if (length(cex.labels) != num_nodes) { 468 | cex.labels = rep(cex.labels, length = num_nodes) 469 | } 470 | cex.labels = cex.labels[aux_ord] 471 | 472 | # ====================================================== 473 | # Plot arc diagram (horizontally or vertically) 474 | # ====================================================== 475 | # auxiliar vector for plotting arcs 476 | z = seq(0, pi, length.out = 100) 477 | 478 | if (horizontal) { 479 | side = 1 480 | } else { 481 | side = 2 482 | } 483 | 484 | if (is.null(xlim)) { 485 | if (horizontal) { 486 | xlim = c(-0.015, 1.015) 487 | x_nodes = centers 488 | } else { 489 | xlims = min_max_margin(radios, above) 490 | xlim = c(xlims$min, xlims$max) 491 | x_nodes = rep(0, num_nodes) 492 | } 493 | } else { 494 | if (horizontal) { 495 | x_nodes = centers 496 | } else { 497 | x_nodes = rep(0, num_nodes) 498 | } 499 | } 500 | 501 | if (is.null(ylim)) { 502 | if (horizontal) { 503 | ylims = min_max_margin(radios, above) 504 | ylim = c(ylims$min, ylims$max) 505 | y_nodes = rep(0, num_nodes) 506 | } else { 507 | ylim = c(-0.015, 1.015) 508 | y_nodes = centers 509 | } 510 | } else { 511 | if (horizontal) { 512 | y_nodes = rep(0, num_nodes) 513 | } else { 514 | y_nodes = centers 515 | } 516 | } 517 | 518 | # open empty plot window 519 | plot(0.5, 0.5, xlim = xlim, ylim = ylim, type = "n", 520 | xlab = "", ylab = "", axes = axes, ...) 521 | # add each edge 522 | for (i in 1L:num_edges) 523 | { 524 | # get radius length 525 | radio = radios[i] 526 | if (horizontal) { 527 | # x-y coords of each arc 528 | x_arc = locs[i] + radio * cos(z) 529 | if (above[i]) { # above axis 530 | y_arc = radio * sin(z) 531 | } else { # below axis 532 | y_arc = radio * sin(-z) 533 | } 534 | } else { 535 | # x-y coords of each arc 536 | y_arc = locs[i] + radio * cos(z) 537 | if (above[i]) { # above axis 538 | x_arc = radio * sin(z) 539 | } else { # below axis 540 | x_arc = radio * sin(-z) 541 | } 542 | } 543 | 544 | # plot arc connecting nodes 545 | lines(x_arc, y_arc, col=col.arcs[i], lwd=lwd.arcs[i], lty=lty.arcs[i], 546 | lend=lend, ljoin=ljoin, lmitre=lmitre) 547 | # add node symbols with points 548 | if (show.nodes) { 549 | points(x=x_nodes, y=y_nodes, pch=pch.nodes, 550 | col=col.nodes, bg=bg.nodes, cex=cex.nodes, lwd=lwd.nodes) 551 | } 552 | # add node labels with mtext 553 | if (show.labels) { 554 | mtext(labels, side=side, line=line, at=centers, cex=cex.labels, outer=outer, 555 | col=col.labels, las=las, font=font, adj=adj, padj=padj, ...) 556 | } 557 | } 558 | } 559 | 560 | 561 | #' @title Node Coordinates 562 | #' 563 | #' @description 564 | #' Computes axis locations of each node. This function can be helpful when 565 | #' you want to separately plot the node labels using the function mtext. 566 | #' 567 | #' @param edgelist basically a two-column matrix with edges 568 | #' (see \code{\link{graph}}) 569 | #' @param sorted logical to indicate if nodes should be sorted 570 | #' @param decreasing logical to indicate type of sorting 571 | #' (used only when \code{sorted=TRUE}) 572 | #' @param ordering optional numeric vector providing the ordering of nodes 573 | #' (when provided, this parameter overrides \code{sorted=TRUE}) 574 | #' @param labels character vector with labels for the nodes 575 | #' @return a vector with the location of nodes in the x-axis 576 | #' @author Gaston Sanchez 577 | #' @seealso \code{\link{arcplot}} 578 | #' @export 579 | #' @examples 580 | #' 581 | #' \dontrun{ 582 | #' # generate a graph 583 | #' some_graph = graph.ring(10) 584 | #' 585 | #' # add names to nodes 586 | #' V(some_graph)$name = letters[1:vcount(some_graph)] 587 | #' 588 | #' # extract edgelist 589 | #' edgelist = get.edgelist(some_graph) 590 | #' 591 | #' # (default) arc diagram 592 | #' arcplot(edgelist, labels=V(some_graph)$name, las=1) 593 | #' 594 | #' # get x-axis coordinates of nodes 595 | #' xcoords = node_coords(edgelist, labels=V(some_graph)$name) 596 | #' 597 | #' # arc diagram with various labels 598 | #' arcplot(edgelist, show.labels=FALSE, show.nodes=TRUE) 599 | #' mtext(V(some_graph)$name, side=1, line=0, at=xcoords) 600 | #' mtext(rep("node",10), side=1, line=1, at=xcoords, col="gray90") 601 | #' } 602 | #' 603 | node_coords <- function( 604 | edgelist, sorted = FALSE, decreasing = FALSE, ordering = NULL, 605 | labels = NULL) 606 | { 607 | # Get graph information 608 | nodes_edges = graph_info(edgelist, sorted = sorted, decreasing = decreasing, 609 | ordering = ordering, labels = labels) 610 | 611 | nodes = nodes_edges$nodes 612 | num_nodes = nodes_edges$num_nodes 613 | num_edges = nodes_edges$num_edges 614 | aux_ord = nodes_edges$aux_ord 615 | labels = nodes_edges$labels 616 | 617 | # x-y node coordinates 618 | centers = xynodes(num_nodes, aux_ord, labels) 619 | } 620 | -------------------------------------------------------------------------------- /lesmiserables.gml: -------------------------------------------------------------------------------- 1 | Creator "igraph version 0.6 Wed Jan 30 10:28:57 2013" 2 | Version 1 3 | graph 4 | [ 5 | directed 0 6 | node 7 | [ 8 | id 0 9 | label "Myriel" 10 | group 1 11 | fill "#BEBADA" 12 | border "#aba7c4" 13 | ] 14 | node 15 | [ 16 | id 1 17 | label "Napoleon" 18 | group 1 19 | fill "#BEBADA" 20 | border "#aba7c4" 21 | ] 22 | node 23 | [ 24 | id 2 25 | label "MlleBaptistine" 26 | group 1 27 | fill "#BEBADA" 28 | border "#aba7c4" 29 | ] 30 | node 31 | [ 32 | id 3 33 | label "MmeMagloire" 34 | group 1 35 | fill "#BEBADA" 36 | border "#aba7c4" 37 | ] 38 | node 39 | [ 40 | id 4 41 | label "CountessDeLo" 42 | group 1 43 | fill "#BEBADA" 44 | border "#aba7c4" 45 | ] 46 | node 47 | [ 48 | id 5 49 | label "Geborand" 50 | group 1 51 | fill "#BEBADA" 52 | border "#aba7c4" 53 | ] 54 | node 55 | [ 56 | id 6 57 | label "Champtercier" 58 | group 1 59 | fill "#BEBADA" 60 | border "#aba7c4" 61 | ] 62 | node 63 | [ 64 | id 7 65 | label "Cravatte" 66 | group 1 67 | fill "#BEBADA" 68 | border "#aba7c4" 69 | ] 70 | node 71 | [ 72 | id 8 73 | label "Count" 74 | group 1 75 | fill "#BEBADA" 76 | border "#aba7c4" 77 | ] 78 | node 79 | [ 80 | id 9 81 | label "OldMan" 82 | group 1 83 | fill "#BEBADA" 84 | border "#aba7c4" 85 | ] 86 | node 87 | [ 88 | id 10 89 | label "Labarre" 90 | group 2 91 | fill "#8b91d4" 92 | border "#6f74a9" 93 | ] 94 | node 95 | [ 96 | id 11 97 | label "Valjean" 98 | group 2 99 | fill "#8b91d4" 100 | border "#6f74a9" 101 | ] 102 | node 103 | [ 104 | id 12 105 | label "Marguerite" 106 | group 3 107 | fill "#67799f" 108 | border "#51607f" 109 | ] 110 | node 111 | [ 112 | id 13 113 | label "MmeDeR" 114 | group 2 115 | fill "#8b91d4" 116 | border "#6f74a9" 117 | ] 118 | node 119 | [ 120 | id 14 121 | label "Isabeau" 122 | group 2 123 | fill "#8b91d4" 124 | border "#6f74a9" 125 | ] 126 | node 127 | [ 128 | id 15 129 | label "Gervais" 130 | group 2 131 | fill "#8b91d4" 132 | border "#6f74a9" 133 | ] 134 | node 135 | [ 136 | id 16 137 | label "Tholomyes" 138 | group 3 139 | fill "#67799f" 140 | border "#51607f" 141 | ] 142 | node 143 | [ 144 | id 17 145 | label "Listolier" 146 | group 3 147 | fill "#67799f" 148 | border "#51607f" 149 | ] 150 | node 151 | [ 152 | id 18 153 | label "Fameuil" 154 | group 3 155 | fill "#67799f" 156 | border "#51607f" 157 | ] 158 | node 159 | [ 160 | id 19 161 | label "Blacheville" 162 | group 3 163 | fill "#67799f" 164 | border "#51607f" 165 | ] 166 | node 167 | [ 168 | id 20 169 | label "Favourite" 170 | group 3 171 | fill "#67799f" 172 | border "#51607f" 173 | ] 174 | node 175 | [ 176 | id 21 177 | label "Dahlia" 178 | group 3 179 | fill "#67799f" 180 | border "#51607f" 181 | ] 182 | node 183 | [ 184 | id 22 185 | label "Zephine" 186 | group 3 187 | fill "#67799f" 188 | border "#51607f" 189 | ] 190 | node 191 | [ 192 | id 23 193 | label "Fantine" 194 | group 3 195 | fill "#67799f" 196 | border "#51607f" 197 | ] 198 | node 199 | [ 200 | id 24 201 | label "MmeThenardier" 202 | group 4 203 | fill "#d3e4a6" 204 | border "#bdcd95" 205 | ] 206 | node 207 | [ 208 | id 25 209 | label "Thenardier" 210 | group 4 211 | fill "#d3e4a6" 212 | border "#bdcd95" 213 | ] 214 | node 215 | [ 216 | id 26 217 | label "Cosette" 218 | group 5 219 | fill "#b2c771" 220 | border "#8e9f5a" 221 | ] 222 | node 223 | [ 224 | id 27 225 | label "Javert" 226 | group 4 227 | fill "#d3e4a6" 228 | border "#bdcd95" 229 | ] 230 | node 231 | [ 232 | id 28 233 | label "Fauchelevent" 234 | group 0 235 | fill "#9ca243" 236 | border "#7c8135" 237 | ] 238 | node 239 | [ 240 | id 29 241 | label "Bamatabois" 242 | group 2 243 | fill "#8b91d4" 244 | border "#6f74a9" 245 | ] 246 | node 247 | [ 248 | id 30 249 | label "Perpetue" 250 | group 3 251 | fill "#67799f" 252 | border "#51607f" 253 | ] 254 | node 255 | [ 256 | id 31 257 | label "Simplice" 258 | group 2 259 | fill "#8b91d4" 260 | border "#6f74a9" 261 | ] 262 | node 263 | [ 264 | id 32 265 | label "Scaufflaire" 266 | group 2 267 | fill "#8b91d4" 268 | border "#6f74a9" 269 | ] 270 | node 271 | [ 272 | id 33 273 | label "Woman1" 274 | group 2 275 | fill "#8b91d4" 276 | border "#6f74a9" 277 | ] 278 | node 279 | [ 280 | id 34 281 | label "Judge" 282 | group 2 283 | fill "#8b91d4" 284 | border "#6f74a9" 285 | ] 286 | node 287 | [ 288 | id 35 289 | label "Champmathieu" 290 | group 2 291 | fill "#8b91d4" 292 | border "#6f74a9" 293 | ] 294 | node 295 | [ 296 | id 36 297 | label "Brevet" 298 | group 2 299 | fill "#8b91d4" 300 | border "#6f74a9" 301 | ] 302 | node 303 | [ 304 | id 37 305 | label "Chenildieu" 306 | group 2 307 | fill "#8b91d4" 308 | border "#6f74a9" 309 | ] 310 | node 311 | [ 312 | id 38 313 | label "Cochepaille" 314 | group 2 315 | fill "#8b91d4" 316 | border "#6f74a9" 317 | ] 318 | node 319 | [ 320 | id 39 321 | label "Pontmercy" 322 | group 4 323 | fill "#d3e4a6" 324 | border "#bdcd95" 325 | ] 326 | node 327 | [ 328 | id 40 329 | label "Boulatruelle" 330 | group 6 331 | fill "#657845" 332 | border "#5a6c3e" 333 | ] 334 | node 335 | [ 336 | id 41 337 | label "Eponine" 338 | group 4 339 | fill "#d3e4a6" 340 | border "#bdcd95" 341 | ] 342 | node 343 | [ 344 | id 42 345 | label "Anzelma" 346 | group 4 347 | fill "#d3e4a6" 348 | border "#bdcd95" 349 | ] 350 | node 351 | [ 352 | id 43 353 | label "Woman2" 354 | group 5 355 | fill "#b2c771" 356 | border "#8e9f5a" 357 | ] 358 | node 359 | [ 360 | id 44 361 | label "MotherInnocent" 362 | group 0 363 | fill "#9ca243" 364 | border "#7c8135" 365 | ] 366 | node 367 | [ 368 | id 45 369 | label "Gribier" 370 | group 0 371 | fill "#9ca243" 372 | border "#7c8135" 373 | ] 374 | node 375 | [ 376 | id 46 377 | label "Jondrette" 378 | group 7 379 | fill "#f3d581" 380 | border "#dabf74" 381 | ] 382 | node 383 | [ 384 | id 47 385 | label "MmeBurgon" 386 | group 7 387 | fill "#f3d581" 388 | border "#dabf74" 389 | ] 390 | node 391 | [ 392 | id 48 393 | label "Gavroche" 394 | group 8 395 | fill "#f0c753" 396 | border "#b89e54" 397 | ] 398 | node 399 | [ 400 | id 49 401 | label "Gillenormand" 402 | group 5 403 | fill "#b2c771" 404 | border "#8e9f5a" 405 | ] 406 | node 407 | [ 408 | id 50 409 | label "Magnon" 410 | group 5 411 | fill "#b2c771" 412 | border "#8e9f5a" 413 | ] 414 | node 415 | [ 416 | id 51 417 | label "MlleGillenormand" 418 | group 5 419 | fill "#b2c771" 420 | border "#8e9f5a" 421 | ] 422 | node 423 | [ 424 | id 52 425 | label "MmePontmercy" 426 | group 5 427 | fill "#b2c771" 428 | border "#8e9f5a" 429 | ] 430 | node 431 | [ 432 | id 53 433 | label "MlleVaubois" 434 | group 5 435 | fill "#b2c771" 436 | border "#8e9f5a" 437 | ] 438 | node 439 | [ 440 | id 54 441 | label "LtGillenormand" 442 | group 5 443 | fill "#b2c771" 444 | border "#8e9f5a" 445 | ] 446 | node 447 | [ 448 | id 55 449 | label "Marius" 450 | group 8 451 | fill "#f0c753" 452 | border "#b89e54" 453 | ] 454 | node 455 | [ 456 | id 56 457 | label "BaronessT" 458 | group 5 459 | fill "#b2c771" 460 | border "#8e9f5a" 461 | ] 462 | node 463 | [ 464 | id 57 465 | label "Mabeuf" 466 | group 8 467 | fill "#f0c753" 468 | border "#b89e54" 469 | ] 470 | node 471 | [ 472 | id 58 473 | label "Enjolras" 474 | group 8 475 | fill "#f0c753" 476 | border "#b89e54" 477 | ] 478 | node 479 | [ 480 | id 59 481 | label "Combeferre" 482 | group 8 483 | fill "#f0c753" 484 | border "#b89e54" 485 | ] 486 | node 487 | [ 488 | id 60 489 | label "Prouvaire" 490 | group 8 491 | fill "#f0c753" 492 | border "#b89e54" 493 | ] 494 | node 495 | [ 496 | id 61 497 | label "Feuilly" 498 | group 8 499 | fill "#f0c753" 500 | border "#b89e54" 501 | ] 502 | node 503 | [ 504 | id 62 505 | label "Courfeyrac" 506 | group 8 507 | fill "#f0c753" 508 | border "#b89e54" 509 | ] 510 | node 511 | [ 512 | id 63 513 | label "Bahorel" 514 | group 8 515 | fill "#f0c753" 516 | border "#b89e54" 517 | ] 518 | node 519 | [ 520 | id 64 521 | label "Bossuet" 522 | group 8 523 | fill "#f0c753" 524 | border "#b89e54" 525 | ] 526 | node 527 | [ 528 | id 65 529 | label "Joly" 530 | group 8 531 | fill "#f0c753" 532 | border "#b89e54" 533 | ] 534 | node 535 | [ 536 | id 66 537 | label "Grantaire" 538 | group 8 539 | fill "#f0c753" 540 | border "#b89e54" 541 | ] 542 | node 543 | [ 544 | id 67 545 | label "MotherPlutarch" 546 | group 9 547 | fill "#b69f60" 548 | border "#a38f56" 549 | ] 550 | node 551 | [ 552 | id 68 553 | label "Gueulemer" 554 | group 4 555 | fill "#d3e4a6" 556 | border "#bdcd95" 557 | ] 558 | node 559 | [ 560 | id 69 561 | label "Babet" 562 | group 4 563 | fill "#d3e4a6" 564 | border "#bdcd95" 565 | ] 566 | node 567 | [ 568 | id 70 569 | label "Claquesous" 570 | group 4 571 | fill "#d3e4a6" 572 | border "#bdcd95" 573 | ] 574 | node 575 | [ 576 | id 71 577 | label "Montparnasse" 578 | group 4 579 | fill "#d3e4a6" 580 | border "#bdcd95" 581 | ] 582 | node 583 | [ 584 | id 72 585 | label "Toussaint" 586 | group 5 587 | fill "#b2c771" 588 | border "#8e9f5a" 589 | ] 590 | node 591 | [ 592 | id 73 593 | label "Child1" 594 | group 10 595 | fill "#988053" 596 | border "#745926" 597 | ] 598 | node 599 | [ 600 | id 74 601 | label "Child2" 602 | group 10 603 | fill "#988053" 604 | border "#745926" 605 | ] 606 | node 607 | [ 608 | id 75 609 | label "Brujon" 610 | group 4 611 | fill "#d3e4a6" 612 | border "#bdcd95" 613 | ] 614 | node 615 | [ 616 | id 76 617 | label "MmeHucheloup" 618 | group 8 619 | fill "#f0c753" 620 | border "#b89e54" 621 | ] 622 | edge 623 | [ 624 | source 1 625 | target 0 626 | value 1 627 | ] 628 | edge 629 | [ 630 | source 2 631 | target 0 632 | value 8 633 | ] 634 | edge 635 | [ 636 | source 3 637 | target 0 638 | value 10 639 | ] 640 | edge 641 | [ 642 | source 3 643 | target 2 644 | value 6 645 | ] 646 | edge 647 | [ 648 | source 4 649 | target 0 650 | value 1 651 | ] 652 | edge 653 | [ 654 | source 5 655 | target 0 656 | value 1 657 | ] 658 | edge 659 | [ 660 | source 6 661 | target 0 662 | value 1 663 | ] 664 | edge 665 | [ 666 | source 7 667 | target 0 668 | value 1 669 | ] 670 | edge 671 | [ 672 | source 8 673 | target 0 674 | value 2 675 | ] 676 | edge 677 | [ 678 | source 9 679 | target 0 680 | value 1 681 | ] 682 | edge 683 | [ 684 | source 11 685 | target 10 686 | value 1 687 | ] 688 | edge 689 | [ 690 | source 11 691 | target 3 692 | value 3 693 | ] 694 | edge 695 | [ 696 | source 11 697 | target 2 698 | value 3 699 | ] 700 | edge 701 | [ 702 | source 11 703 | target 0 704 | value 5 705 | ] 706 | edge 707 | [ 708 | source 12 709 | target 11 710 | value 1 711 | ] 712 | edge 713 | [ 714 | source 13 715 | target 11 716 | value 1 717 | ] 718 | edge 719 | [ 720 | source 14 721 | target 11 722 | value 1 723 | ] 724 | edge 725 | [ 726 | source 15 727 | target 11 728 | value 1 729 | ] 730 | edge 731 | [ 732 | source 17 733 | target 16 734 | value 4 735 | ] 736 | edge 737 | [ 738 | source 18 739 | target 16 740 | value 4 741 | ] 742 | edge 743 | [ 744 | source 18 745 | target 17 746 | value 4 747 | ] 748 | edge 749 | [ 750 | source 19 751 | target 16 752 | value 4 753 | ] 754 | edge 755 | [ 756 | source 19 757 | target 17 758 | value 4 759 | ] 760 | edge 761 | [ 762 | source 19 763 | target 18 764 | value 4 765 | ] 766 | edge 767 | [ 768 | source 20 769 | target 16 770 | value 3 771 | ] 772 | edge 773 | [ 774 | source 20 775 | target 17 776 | value 3 777 | ] 778 | edge 779 | [ 780 | source 20 781 | target 18 782 | value 3 783 | ] 784 | edge 785 | [ 786 | source 20 787 | target 19 788 | value 4 789 | ] 790 | edge 791 | [ 792 | source 21 793 | target 16 794 | value 3 795 | ] 796 | edge 797 | [ 798 | source 21 799 | target 17 800 | value 3 801 | ] 802 | edge 803 | [ 804 | source 21 805 | target 18 806 | value 3 807 | ] 808 | edge 809 | [ 810 | source 21 811 | target 19 812 | value 3 813 | ] 814 | edge 815 | [ 816 | source 21 817 | target 20 818 | value 5 819 | ] 820 | edge 821 | [ 822 | source 22 823 | target 16 824 | value 3 825 | ] 826 | edge 827 | [ 828 | source 22 829 | target 17 830 | value 3 831 | ] 832 | edge 833 | [ 834 | source 22 835 | target 18 836 | value 3 837 | ] 838 | edge 839 | [ 840 | source 22 841 | target 19 842 | value 3 843 | ] 844 | edge 845 | [ 846 | source 22 847 | target 20 848 | value 4 849 | ] 850 | edge 851 | [ 852 | source 22 853 | target 21 854 | value 4 855 | ] 856 | edge 857 | [ 858 | source 23 859 | target 16 860 | value 3 861 | ] 862 | edge 863 | [ 864 | source 23 865 | target 17 866 | value 3 867 | ] 868 | edge 869 | [ 870 | source 23 871 | target 18 872 | value 3 873 | ] 874 | edge 875 | [ 876 | source 23 877 | target 19 878 | value 3 879 | ] 880 | edge 881 | [ 882 | source 23 883 | target 20 884 | value 4 885 | ] 886 | edge 887 | [ 888 | source 23 889 | target 21 890 | value 4 891 | ] 892 | edge 893 | [ 894 | source 23 895 | target 22 896 | value 4 897 | ] 898 | edge 899 | [ 900 | source 23 901 | target 12 902 | value 2 903 | ] 904 | edge 905 | [ 906 | source 23 907 | target 11 908 | value 9 909 | ] 910 | edge 911 | [ 912 | source 24 913 | target 23 914 | value 2 915 | ] 916 | edge 917 | [ 918 | source 24 919 | target 11 920 | value 7 921 | ] 922 | edge 923 | [ 924 | source 25 925 | target 24 926 | value 13 927 | ] 928 | edge 929 | [ 930 | source 25 931 | target 23 932 | value 1 933 | ] 934 | edge 935 | [ 936 | source 25 937 | target 11 938 | value 12 939 | ] 940 | edge 941 | [ 942 | source 26 943 | target 24 944 | value 4 945 | ] 946 | edge 947 | [ 948 | source 26 949 | target 11 950 | value 31 951 | ] 952 | edge 953 | [ 954 | source 26 955 | target 16 956 | value 1 957 | ] 958 | edge 959 | [ 960 | source 26 961 | target 25 962 | value 1 963 | ] 964 | edge 965 | [ 966 | source 27 967 | target 11 968 | value 17 969 | ] 970 | edge 971 | [ 972 | source 27 973 | target 23 974 | value 5 975 | ] 976 | edge 977 | [ 978 | source 27 979 | target 25 980 | value 5 981 | ] 982 | edge 983 | [ 984 | source 27 985 | target 24 986 | value 1 987 | ] 988 | edge 989 | [ 990 | source 27 991 | target 26 992 | value 1 993 | ] 994 | edge 995 | [ 996 | source 28 997 | target 11 998 | value 8 999 | ] 1000 | edge 1001 | [ 1002 | source 28 1003 | target 27 1004 | value 1 1005 | ] 1006 | edge 1007 | [ 1008 | source 29 1009 | target 23 1010 | value 1 1011 | ] 1012 | edge 1013 | [ 1014 | source 29 1015 | target 27 1016 | value 1 1017 | ] 1018 | edge 1019 | [ 1020 | source 29 1021 | target 11 1022 | value 2 1023 | ] 1024 | edge 1025 | [ 1026 | source 30 1027 | target 23 1028 | value 1 1029 | ] 1030 | edge 1031 | [ 1032 | source 31 1033 | target 30 1034 | value 2 1035 | ] 1036 | edge 1037 | [ 1038 | source 31 1039 | target 11 1040 | value 3 1041 | ] 1042 | edge 1043 | [ 1044 | source 31 1045 | target 23 1046 | value 2 1047 | ] 1048 | edge 1049 | [ 1050 | source 31 1051 | target 27 1052 | value 1 1053 | ] 1054 | edge 1055 | [ 1056 | source 32 1057 | target 11 1058 | value 1 1059 | ] 1060 | edge 1061 | [ 1062 | source 33 1063 | target 11 1064 | value 2 1065 | ] 1066 | edge 1067 | [ 1068 | source 33 1069 | target 27 1070 | value 1 1071 | ] 1072 | edge 1073 | [ 1074 | source 34 1075 | target 11 1076 | value 3 1077 | ] 1078 | edge 1079 | [ 1080 | source 34 1081 | target 29 1082 | value 2 1083 | ] 1084 | edge 1085 | [ 1086 | source 35 1087 | target 11 1088 | value 3 1089 | ] 1090 | edge 1091 | [ 1092 | source 35 1093 | target 34 1094 | value 3 1095 | ] 1096 | edge 1097 | [ 1098 | source 35 1099 | target 29 1100 | value 2 1101 | ] 1102 | edge 1103 | [ 1104 | source 36 1105 | target 34 1106 | value 2 1107 | ] 1108 | edge 1109 | [ 1110 | source 36 1111 | target 35 1112 | value 2 1113 | ] 1114 | edge 1115 | [ 1116 | source 36 1117 | target 11 1118 | value 2 1119 | ] 1120 | edge 1121 | [ 1122 | source 36 1123 | target 29 1124 | value 1 1125 | ] 1126 | edge 1127 | [ 1128 | source 37 1129 | target 34 1130 | value 2 1131 | ] 1132 | edge 1133 | [ 1134 | source 37 1135 | target 35 1136 | value 2 1137 | ] 1138 | edge 1139 | [ 1140 | source 37 1141 | target 36 1142 | value 2 1143 | ] 1144 | edge 1145 | [ 1146 | source 37 1147 | target 11 1148 | value 2 1149 | ] 1150 | edge 1151 | [ 1152 | source 37 1153 | target 29 1154 | value 1 1155 | ] 1156 | edge 1157 | [ 1158 | source 38 1159 | target 34 1160 | value 2 1161 | ] 1162 | edge 1163 | [ 1164 | source 38 1165 | target 35 1166 | value 2 1167 | ] 1168 | edge 1169 | [ 1170 | source 38 1171 | target 36 1172 | value 2 1173 | ] 1174 | edge 1175 | [ 1176 | source 38 1177 | target 37 1178 | value 2 1179 | ] 1180 | edge 1181 | [ 1182 | source 38 1183 | target 11 1184 | value 2 1185 | ] 1186 | edge 1187 | [ 1188 | source 38 1189 | target 29 1190 | value 1 1191 | ] 1192 | edge 1193 | [ 1194 | source 39 1195 | target 25 1196 | value 1 1197 | ] 1198 | edge 1199 | [ 1200 | source 40 1201 | target 25 1202 | value 1 1203 | ] 1204 | edge 1205 | [ 1206 | source 41 1207 | target 24 1208 | value 2 1209 | ] 1210 | edge 1211 | [ 1212 | source 41 1213 | target 25 1214 | value 3 1215 | ] 1216 | edge 1217 | [ 1218 | source 42 1219 | target 41 1220 | value 2 1221 | ] 1222 | edge 1223 | [ 1224 | source 42 1225 | target 25 1226 | value 2 1227 | ] 1228 | edge 1229 | [ 1230 | source 42 1231 | target 24 1232 | value 1 1233 | ] 1234 | edge 1235 | [ 1236 | source 43 1237 | target 11 1238 | value 3 1239 | ] 1240 | edge 1241 | [ 1242 | source 43 1243 | target 26 1244 | value 1 1245 | ] 1246 | edge 1247 | [ 1248 | source 43 1249 | target 27 1250 | value 1 1251 | ] 1252 | edge 1253 | [ 1254 | source 44 1255 | target 28 1256 | value 3 1257 | ] 1258 | edge 1259 | [ 1260 | source 44 1261 | target 11 1262 | value 1 1263 | ] 1264 | edge 1265 | [ 1266 | source 45 1267 | target 28 1268 | value 2 1269 | ] 1270 | edge 1271 | [ 1272 | source 47 1273 | target 46 1274 | value 1 1275 | ] 1276 | edge 1277 | [ 1278 | source 48 1279 | target 47 1280 | value 2 1281 | ] 1282 | edge 1283 | [ 1284 | source 48 1285 | target 25 1286 | value 1 1287 | ] 1288 | edge 1289 | [ 1290 | source 48 1291 | target 27 1292 | value 1 1293 | ] 1294 | edge 1295 | [ 1296 | source 48 1297 | target 11 1298 | value 1 1299 | ] 1300 | edge 1301 | [ 1302 | source 49 1303 | target 26 1304 | value 3 1305 | ] 1306 | edge 1307 | [ 1308 | source 49 1309 | target 11 1310 | value 2 1311 | ] 1312 | edge 1313 | [ 1314 | source 50 1315 | target 49 1316 | value 1 1317 | ] 1318 | edge 1319 | [ 1320 | source 50 1321 | target 24 1322 | value 1 1323 | ] 1324 | edge 1325 | [ 1326 | source 51 1327 | target 49 1328 | value 9 1329 | ] 1330 | edge 1331 | [ 1332 | source 51 1333 | target 26 1334 | value 2 1335 | ] 1336 | edge 1337 | [ 1338 | source 51 1339 | target 11 1340 | value 2 1341 | ] 1342 | edge 1343 | [ 1344 | source 52 1345 | target 51 1346 | value 1 1347 | ] 1348 | edge 1349 | [ 1350 | source 52 1351 | target 39 1352 | value 1 1353 | ] 1354 | edge 1355 | [ 1356 | source 53 1357 | target 51 1358 | value 1 1359 | ] 1360 | edge 1361 | [ 1362 | source 54 1363 | target 51 1364 | value 2 1365 | ] 1366 | edge 1367 | [ 1368 | source 54 1369 | target 49 1370 | value 1 1371 | ] 1372 | edge 1373 | [ 1374 | source 54 1375 | target 26 1376 | value 1 1377 | ] 1378 | edge 1379 | [ 1380 | source 55 1381 | target 51 1382 | value 6 1383 | ] 1384 | edge 1385 | [ 1386 | source 55 1387 | target 49 1388 | value 12 1389 | ] 1390 | edge 1391 | [ 1392 | source 55 1393 | target 39 1394 | value 1 1395 | ] 1396 | edge 1397 | [ 1398 | source 55 1399 | target 54 1400 | value 1 1401 | ] 1402 | edge 1403 | [ 1404 | source 55 1405 | target 26 1406 | value 21 1407 | ] 1408 | edge 1409 | [ 1410 | source 55 1411 | target 11 1412 | value 19 1413 | ] 1414 | edge 1415 | [ 1416 | source 55 1417 | target 16 1418 | value 1 1419 | ] 1420 | edge 1421 | [ 1422 | source 55 1423 | target 25 1424 | value 2 1425 | ] 1426 | edge 1427 | [ 1428 | source 55 1429 | target 41 1430 | value 5 1431 | ] 1432 | edge 1433 | [ 1434 | source 55 1435 | target 48 1436 | value 4 1437 | ] 1438 | edge 1439 | [ 1440 | source 56 1441 | target 49 1442 | value 1 1443 | ] 1444 | edge 1445 | [ 1446 | source 56 1447 | target 55 1448 | value 1 1449 | ] 1450 | edge 1451 | [ 1452 | source 57 1453 | target 55 1454 | value 1 1455 | ] 1456 | edge 1457 | [ 1458 | source 57 1459 | target 41 1460 | value 1 1461 | ] 1462 | edge 1463 | [ 1464 | source 57 1465 | target 48 1466 | value 1 1467 | ] 1468 | edge 1469 | [ 1470 | source 58 1471 | target 55 1472 | value 7 1473 | ] 1474 | edge 1475 | [ 1476 | source 58 1477 | target 48 1478 | value 7 1479 | ] 1480 | edge 1481 | [ 1482 | source 58 1483 | target 27 1484 | value 6 1485 | ] 1486 | edge 1487 | [ 1488 | source 58 1489 | target 57 1490 | value 1 1491 | ] 1492 | edge 1493 | [ 1494 | source 58 1495 | target 11 1496 | value 4 1497 | ] 1498 | edge 1499 | [ 1500 | source 59 1501 | target 58 1502 | value 15 1503 | ] 1504 | edge 1505 | [ 1506 | source 59 1507 | target 55 1508 | value 5 1509 | ] 1510 | edge 1511 | [ 1512 | source 59 1513 | target 48 1514 | value 6 1515 | ] 1516 | edge 1517 | [ 1518 | source 59 1519 | target 57 1520 | value 2 1521 | ] 1522 | edge 1523 | [ 1524 | source 60 1525 | target 48 1526 | value 1 1527 | ] 1528 | edge 1529 | [ 1530 | source 60 1531 | target 58 1532 | value 4 1533 | ] 1534 | edge 1535 | [ 1536 | source 60 1537 | target 59 1538 | value 2 1539 | ] 1540 | edge 1541 | [ 1542 | source 61 1543 | target 48 1544 | value 2 1545 | ] 1546 | edge 1547 | [ 1548 | source 61 1549 | target 58 1550 | value 6 1551 | ] 1552 | edge 1553 | [ 1554 | source 61 1555 | target 60 1556 | value 2 1557 | ] 1558 | edge 1559 | [ 1560 | source 61 1561 | target 59 1562 | value 5 1563 | ] 1564 | edge 1565 | [ 1566 | source 61 1567 | target 57 1568 | value 1 1569 | ] 1570 | edge 1571 | [ 1572 | source 61 1573 | target 55 1574 | value 1 1575 | ] 1576 | edge 1577 | [ 1578 | source 62 1579 | target 55 1580 | value 9 1581 | ] 1582 | edge 1583 | [ 1584 | source 62 1585 | target 58 1586 | value 17 1587 | ] 1588 | edge 1589 | [ 1590 | source 62 1591 | target 59 1592 | value 13 1593 | ] 1594 | edge 1595 | [ 1596 | source 62 1597 | target 48 1598 | value 7 1599 | ] 1600 | edge 1601 | [ 1602 | source 62 1603 | target 57 1604 | value 2 1605 | ] 1606 | edge 1607 | [ 1608 | source 62 1609 | target 41 1610 | value 1 1611 | ] 1612 | edge 1613 | [ 1614 | source 62 1615 | target 61 1616 | value 6 1617 | ] 1618 | edge 1619 | [ 1620 | source 62 1621 | target 60 1622 | value 3 1623 | ] 1624 | edge 1625 | [ 1626 | source 63 1627 | target 59 1628 | value 5 1629 | ] 1630 | edge 1631 | [ 1632 | source 63 1633 | target 48 1634 | value 5 1635 | ] 1636 | edge 1637 | [ 1638 | source 63 1639 | target 62 1640 | value 6 1641 | ] 1642 | edge 1643 | [ 1644 | source 63 1645 | target 57 1646 | value 2 1647 | ] 1648 | edge 1649 | [ 1650 | source 63 1651 | target 58 1652 | value 4 1653 | ] 1654 | edge 1655 | [ 1656 | source 63 1657 | target 61 1658 | value 3 1659 | ] 1660 | edge 1661 | [ 1662 | source 63 1663 | target 60 1664 | value 2 1665 | ] 1666 | edge 1667 | [ 1668 | source 63 1669 | target 55 1670 | value 1 1671 | ] 1672 | edge 1673 | [ 1674 | source 64 1675 | target 55 1676 | value 5 1677 | ] 1678 | edge 1679 | [ 1680 | source 64 1681 | target 62 1682 | value 12 1683 | ] 1684 | edge 1685 | [ 1686 | source 64 1687 | target 48 1688 | value 5 1689 | ] 1690 | edge 1691 | [ 1692 | source 64 1693 | target 63 1694 | value 4 1695 | ] 1696 | edge 1697 | [ 1698 | source 64 1699 | target 58 1700 | value 10 1701 | ] 1702 | edge 1703 | [ 1704 | source 64 1705 | target 61 1706 | value 6 1707 | ] 1708 | edge 1709 | [ 1710 | source 64 1711 | target 60 1712 | value 2 1713 | ] 1714 | edge 1715 | [ 1716 | source 64 1717 | target 59 1718 | value 9 1719 | ] 1720 | edge 1721 | [ 1722 | source 64 1723 | target 57 1724 | value 1 1725 | ] 1726 | edge 1727 | [ 1728 | source 64 1729 | target 11 1730 | value 1 1731 | ] 1732 | edge 1733 | [ 1734 | source 65 1735 | target 63 1736 | value 5 1737 | ] 1738 | edge 1739 | [ 1740 | source 65 1741 | target 64 1742 | value 7 1743 | ] 1744 | edge 1745 | [ 1746 | source 65 1747 | target 48 1748 | value 3 1749 | ] 1750 | edge 1751 | [ 1752 | source 65 1753 | target 62 1754 | value 5 1755 | ] 1756 | edge 1757 | [ 1758 | source 65 1759 | target 58 1760 | value 5 1761 | ] 1762 | edge 1763 | [ 1764 | source 65 1765 | target 61 1766 | value 5 1767 | ] 1768 | edge 1769 | [ 1770 | source 65 1771 | target 60 1772 | value 2 1773 | ] 1774 | edge 1775 | [ 1776 | source 65 1777 | target 59 1778 | value 5 1779 | ] 1780 | edge 1781 | [ 1782 | source 65 1783 | target 57 1784 | value 1 1785 | ] 1786 | edge 1787 | [ 1788 | source 65 1789 | target 55 1790 | value 2 1791 | ] 1792 | edge 1793 | [ 1794 | source 66 1795 | target 64 1796 | value 3 1797 | ] 1798 | edge 1799 | [ 1800 | source 66 1801 | target 58 1802 | value 3 1803 | ] 1804 | edge 1805 | [ 1806 | source 66 1807 | target 59 1808 | value 1 1809 | ] 1810 | edge 1811 | [ 1812 | source 66 1813 | target 62 1814 | value 2 1815 | ] 1816 | edge 1817 | [ 1818 | source 66 1819 | target 65 1820 | value 2 1821 | ] 1822 | edge 1823 | [ 1824 | source 66 1825 | target 48 1826 | value 1 1827 | ] 1828 | edge 1829 | [ 1830 | source 66 1831 | target 63 1832 | value 1 1833 | ] 1834 | edge 1835 | [ 1836 | source 66 1837 | target 61 1838 | value 1 1839 | ] 1840 | edge 1841 | [ 1842 | source 66 1843 | target 60 1844 | value 1 1845 | ] 1846 | edge 1847 | [ 1848 | source 67 1849 | target 57 1850 | value 3 1851 | ] 1852 | edge 1853 | [ 1854 | source 68 1855 | target 25 1856 | value 5 1857 | ] 1858 | edge 1859 | [ 1860 | source 68 1861 | target 11 1862 | value 1 1863 | ] 1864 | edge 1865 | [ 1866 | source 68 1867 | target 24 1868 | value 1 1869 | ] 1870 | edge 1871 | [ 1872 | source 68 1873 | target 27 1874 | value 1 1875 | ] 1876 | edge 1877 | [ 1878 | source 68 1879 | target 48 1880 | value 1 1881 | ] 1882 | edge 1883 | [ 1884 | source 68 1885 | target 41 1886 | value 1 1887 | ] 1888 | edge 1889 | [ 1890 | source 69 1891 | target 25 1892 | value 6 1893 | ] 1894 | edge 1895 | [ 1896 | source 69 1897 | target 68 1898 | value 6 1899 | ] 1900 | edge 1901 | [ 1902 | source 69 1903 | target 11 1904 | value 1 1905 | ] 1906 | edge 1907 | [ 1908 | source 69 1909 | target 24 1910 | value 1 1911 | ] 1912 | edge 1913 | [ 1914 | source 69 1915 | target 27 1916 | value 2 1917 | ] 1918 | edge 1919 | [ 1920 | source 69 1921 | target 48 1922 | value 1 1923 | ] 1924 | edge 1925 | [ 1926 | source 69 1927 | target 41 1928 | value 1 1929 | ] 1930 | edge 1931 | [ 1932 | source 70 1933 | target 25 1934 | value 4 1935 | ] 1936 | edge 1937 | [ 1938 | source 70 1939 | target 69 1940 | value 4 1941 | ] 1942 | edge 1943 | [ 1944 | source 70 1945 | target 68 1946 | value 4 1947 | ] 1948 | edge 1949 | [ 1950 | source 70 1951 | target 11 1952 | value 1 1953 | ] 1954 | edge 1955 | [ 1956 | source 70 1957 | target 24 1958 | value 1 1959 | ] 1960 | edge 1961 | [ 1962 | source 70 1963 | target 27 1964 | value 1 1965 | ] 1966 | edge 1967 | [ 1968 | source 70 1969 | target 41 1970 | value 1 1971 | ] 1972 | edge 1973 | [ 1974 | source 70 1975 | target 58 1976 | value 1 1977 | ] 1978 | edge 1979 | [ 1980 | source 71 1981 | target 27 1982 | value 1 1983 | ] 1984 | edge 1985 | [ 1986 | source 71 1987 | target 69 1988 | value 2 1989 | ] 1990 | edge 1991 | [ 1992 | source 71 1993 | target 68 1994 | value 2 1995 | ] 1996 | edge 1997 | [ 1998 | source 71 1999 | target 70 2000 | value 2 2001 | ] 2002 | edge 2003 | [ 2004 | source 71 2005 | target 11 2006 | value 1 2007 | ] 2008 | edge 2009 | [ 2010 | source 71 2011 | target 48 2012 | value 1 2013 | ] 2014 | edge 2015 | [ 2016 | source 71 2017 | target 41 2018 | value 1 2019 | ] 2020 | edge 2021 | [ 2022 | source 71 2023 | target 25 2024 | value 1 2025 | ] 2026 | edge 2027 | [ 2028 | source 72 2029 | target 26 2030 | value 2 2031 | ] 2032 | edge 2033 | [ 2034 | source 72 2035 | target 27 2036 | value 1 2037 | ] 2038 | edge 2039 | [ 2040 | source 72 2041 | target 11 2042 | value 1 2043 | ] 2044 | edge 2045 | [ 2046 | source 73 2047 | target 48 2048 | value 2 2049 | ] 2050 | edge 2051 | [ 2052 | source 74 2053 | target 48 2054 | value 2 2055 | ] 2056 | edge 2057 | [ 2058 | source 74 2059 | target 73 2060 | value 3 2061 | ] 2062 | edge 2063 | [ 2064 | source 75 2065 | target 69 2066 | value 3 2067 | ] 2068 | edge 2069 | [ 2070 | source 75 2071 | target 68 2072 | value 3 2073 | ] 2074 | edge 2075 | [ 2076 | source 75 2077 | target 25 2078 | value 3 2079 | ] 2080 | edge 2081 | [ 2082 | source 75 2083 | target 48 2084 | value 1 2085 | ] 2086 | edge 2087 | [ 2088 | source 75 2089 | target 41 2090 | value 1 2091 | ] 2092 | edge 2093 | [ 2094 | source 75 2095 | target 70 2096 | value 1 2097 | ] 2098 | edge 2099 | [ 2100 | source 75 2101 | target 71 2102 | value 1 2103 | ] 2104 | edge 2105 | [ 2106 | source 76 2107 | target 64 2108 | value 1 2109 | ] 2110 | edge 2111 | [ 2112 | source 76 2113 | target 65 2114 | value 1 2115 | ] 2116 | edge 2117 | [ 2118 | source 76 2119 | target 66 2120 | value 1 2121 | ] 2122 | edge 2123 | [ 2124 | source 76 2125 | target 63 2126 | value 1 2127 | ] 2128 | edge 2129 | [ 2130 | source 76 2131 | target 62 2132 | value 1 2133 | ] 2134 | edge 2135 | [ 2136 | source 76 2137 | target 48 2138 | value 1 2139 | ] 2140 | edge 2141 | [ 2142 | source 76 2143 | target 58 2144 | value 1 2145 | ] 2146 | ] 2147 | --------------------------------------------------------------------------------