The goal is to familiarize with the R package igraph.

Official website: http://igraph.org/r/

Be careful: igraph has also been developed in C and Python. If you do a search on the web you might arrive on http://igraph.org/c/ or http://igraph.org/python/ rather than http://igraph.org/r/

If you want to go further with igraph you can also have a look at that tutorial: http://kateto.net/networks-r-igraph

igraph package

Install the package igraph and load the library

install.packages("igraph")
library(igraph)
## 
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
## 
##     decompose, spectrum
## The following object is masked from 'package:base':
## 
##     union

1. Create a toy graph by hand

1.1. Giving the list of edges

There are 2 possible formats: either a vector that concatenates the indexes of linked nodes or a matrix with 2 rows.

EdgeList1 <- c(1,2, 1,3, 2,3, 3,5, 2,4, 4,5, 5,6, 4,6, 4,7, 6,7, 3,4)
EdgeList2 <- matrix(EdgeList1,nrow=2)
g1 <- graph(edges=EdgeList1, directed=FALSE)
g2 <- graph(edges=EdgeList2, directed=FALSE)
par(mfrow=c(1,2))
plot(g1)
plot(g2)

You obtain an object with class igraph:

class(g1)
## [1] "igraph"

You can specify the number of nodes \(n\) (in particular when there are isolated nodes):

g3 <- graph(edges=EdgeList1, n=9, directed=FALSE)
plot(g3)

Nodes are not necessarily of the numeric type:

EdgeListNames <- c("Eric", "Erwan", "Erwan","Ana")
g4 <- graph(edges=EdgeListNames)
plot(g4)

# Note that by default, the graph is directed 

With isolated nodes:

g5 <- graph(edges=EdgeListNames, isolates="Paul")
plot(g5)

1.2. By reading a data.frame structure containing the list of edges:

Download file from: http://www.sociopatterns.org/datasets/high-school-contact-and-friendship-networks/

Dataset (csv format) gathers friendship relationships among high-school students.

friends <- read.table(file='Friendship-network_data_2013.csv')
head(friends)
gfriends <- graph_from_data_frame(friends, directed=TRUE) 
gfriends
## IGRAPH 3f9b0d4 DN-- 134 668 -- 
## + attr: name (v/c)
## + edges from 3f9b0d4 (vertex names):
##  [1] 1 ->55  1 ->205 1 ->272 1 ->494 1 ->779 1 ->894 3 ->1   3 ->28  3 ->147
## [10] 3 ->272 3 ->407 3 ->674 3 ->884 27->63  27->173 28->202 28->327 28->353
## [19] 28->407 28->429 28->441 28->492 28->545 32->440 32->624 32->797 32->920
## [28] 34->151 34->277 34->502 34->866 45->48  45->79  45->335 45->496 45->601
## [37] 45->674 45->765 46->117 46->196 46->257 46->268 48->45  48->79  48->496
## [46] 55->1   55->170 55->205 55->252 55->272 55->779 55->883 55->894 61->797
## [55] 63->27  63->125 63->173 70->101 70->132 70->240 70->425 70->447 72->407
## [64] 72->674 72->857 79->45  79->48  79->335 79->496 79->601 79->674 79->765
## + ... omitted several edges
class(gfriends)
## [1] "igraph"
plot(gfriends)

You can also import other data.frame; try with a dataset containing information about media: the first file Dataset1-Media-Example-NODES.csv contains information about the nodes and the second one Dataset1-Media-Example-EDGES.csv contains the list of interactions (these are valued and of several different types):

nodes <- read.csv("Dataset1-Media-Example-NODES.csv", header=TRUE, as.is=TRUE)
head(nodes)
links <- read.csv("Dataset1-Media-Example-EDGES.csv", header=TRUE, as.is=TRUE)
head(links)
net <- graph_from_data_frame(d=links, vertices=nodes, directed=TRUE) 
class(net)
## [1] "igraph"
plot(net)

1.3. Using a file whose format is adapted to igraph:

Function read_graph is adapted to certain graph formats:

# usage: 
read_graph(file, format = c("edgelist", "pajek", "ncol", "lgl", "graphml", "dimacs", "graphdb", "gml", "dl"), ...)

The file lesmis.gml contains the weighted network of co-appearances of characters in Victor Hugo’s novel Les Miserables. Nodes represent characters as indicated by the labels and edges connect any pair of characters that appear in the same chapter of the book. The values on the edges are the number of such co-appearances. http://www-personal.umich.edu/~mejn/netdata/

miserab <- read_graph(file='lesmis.gml', format="gml") 
class(miserab)
## [1] "igraph"
plot(miserab)

1.4. Using an adjacency matrix

A <- matrix(c(0,0,0,0,0,0,1,1,0,1,0,1,0,1,1,0), 4, 4)
A
##      [,1] [,2] [,3] [,4]
## [1,]    0    0    0    0
## [2,]    0    0    1    1
## [3,]    0    1    0    1
## [4,]    0    1    1    0
plot(graph_from_adjacency_matrix(A, mode='undirected'))

2. Adjacency matrix

You can convert a graph into its adjacency matrix:

Afriends <- as_adj(gfriends)
dim(Afriends)
## [1] 134 134

Beware: by default as_adj creates a matrix with sparse format and certain classical operations are. not possible :

is.matrix(Afriends)
## [1] FALSE
class(Afriends)
## [1] "dgCMatrix"
## attr(,"package")
## [1] "Matrix"
t(Afriends)
## Error in t.default(Afriends): argument is not a matrix

To correct for that, just use option sparse=FALSE:

Afriends <- as_adj(gfriends, sparse=FALSE)
is.matrix(Afriends)
## [1] TRUE

3. Properties of a simple graph

Get familiar with the following functions by applying them to the graphs created above. Also use the package documentation (with help()) and READ it!

vcount()
ecount()
V()
E()
is.directed()

4. Graphs visualisation

4.1 Network layouts: common algorithms for visualisation

To know more about that: https://igraph.org/r/doc/layout_.html

plot(gfriends)

To choose a specific layout, use the following option (use autocompletion to see the possible layouts):

plot(gfriends, layout=layout_as_star)

plot(gfriends, layout=layout_in_circle)

plot(gfriends, layout=layout_randomly)

Two popular visualization algorithms for having visualizations deemed “aesthetic”. If you want more information: https://halshs.archives-ouvertes.fr/halshs-00839905/document

plot(gfriends, layout=layout.fruchterman.reingold)

plot(gfriends, layout=layout.kamada.kawai)

4.2 Embellish your figures with igraph

To see all options of plot() just type ?igraph.plotting

The most common ones are:

  • vertex.color, vertex.shape, vertex.size, vertex.label color, shape, size and labels of the nodes
  • edge.color, edge.label edge color and labels
plot(net)

plot(net, edge.arrow.size=.4)

plot(net, vertex.color="orange", edge.color="blue", vertex.label.color="black", edge.arrow.size=.4)

If we want to use additional information to color the nodes according to the covariates (here the type of media, the size of the nodes according to the audience, the thickness of the edges according to their weight…) or on the edges (here valued and of different types) You can find this information here:

vertex_attr(net)
## $name
##  [1] "s01" "s02" "s03" "s04" "s05" "s06" "s07" "s08" "s09" "s10" "s11" "s12"
## [13] "s13" "s14" "s15" "s16" "s17"
## 
## $media
##  [1] "NY Times"            "Washington Post"     "Wall Street Journal"
##  [4] "USA Today"           "LA Times"            "New York Post"      
##  [7] "CNN"                 "MSNBC"               "FOX News"           
## [10] "ABC"                 "BBC"                 "Yahoo News"         
## [13] "Google News"         "Reuters.com"         "NYTimes.com"        
## [16] "WashingtonPost.com"  "AOL.com"            
## 
## $media.type
##  [1] 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 3
## 
## $type.label
##  [1] "Newspaper" "Newspaper" "Newspaper" "Newspaper" "Newspaper" "Newspaper"
##  [7] "TV"        "TV"        "TV"        "TV"        "TV"        "Online"   
## [13] "Online"    "Online"    "Online"    "Online"    "Online"   
## 
## $audience.size
##  [1] 20 25 30 32 20 50 56 34 60 23 34 33 23 12 24 28 33
V(net)$media
##  [1] "NY Times"            "Washington Post"     "Wall Street Journal"
##  [4] "USA Today"           "LA Times"            "New York Post"      
##  [7] "CNN"                 "MSNBC"               "FOX News"           
## [10] "ABC"                 "BBC"                 "Yahoo News"         
## [13] "Google News"         "Reuters.com"         "NYTimes.com"        
## [16] "WashingtonPost.com"  "AOL.com"
edge_attr(net)
## $weight
##  [1] 10 12 22 21 22 21 21 11 12 22 23 20 11 11 21 23 21 21 21 22 21 21 21 23 21
## [26] 22 22 21 21  2  5  1  1  2  2  3  1  1  1  1  2  2  4  2  4  4  4  1  1  1
## [51]  1  1
## 
## $type
##  [1] "hyperlink" "hyperlink" "hyperlink" "hyperlink" "mention"   "mention"  
##  [7] "mention"   "mention"   "mention"   "hyperlink" "hyperlink" "mention"  
## [13] "hyperlink" "hyperlink" "mention"   "hyperlink" "hyperlink" "mention"  
## [19] "mention"   "mention"   "hyperlink" "hyperlink" "hyperlink" "hyperlink"
## [25] "hyperlink" "hyperlink" "mention"   "mention"   "hyperlink" "hyperlink"
## [31] "hyperlink" "hyperlink" "mention"   "hyperlink" "mention"   "hyperlink"
## [37] "mention"   "hyperlink" "mention"   "hyperlink" "mention"   "mention"  
## [43] "hyperlink" "hyperlink" "hyperlink" "mention"   "hyperlink" "hyperlink"
## [49] "mention"   "hyperlink" "hyperlink" "mention"
E(net)$weight
##  [1] 10 12 22 21 22 21 21 11 12 22 23 20 11 11 21 23 21 21 21 22 21 21 21 23 21
## [26] 22 22 21 21  2  5  1  1  2  2  3  1  1  1  1  2  2  4  2  4  4  4  1  1  1
## [51]  1  1
plot(net, vertex.label=V(net)$media, edge.arrow.size=.4)

plot(net, vertex.label=V(net)$media, edge.arrow.size=.4, vertex.color=V(net)$media.type)

plot(net, vertex.label=V(net)$media, edge.arrow.size=.4, vertex.color=V(net)$media.type, vertex.size=V(net)$audience.size)

plot(net, vertex.label=V(net)$media, vertex.color=V(net)$media.type, vertex.size=V(net)$audience.size, edge.width=E(net)$weight)

To change the color of the link based on its type

E(net)$color[E(net)$type=="hyperlink"]<-"blue"
E(net)$color[E(net)$type=="mention"]<-"red"
plot(net, edge.arrow.size=.4)

Exercise 1

Search the web for graphs and import them onto your machine (you will keep the data recovery address as a comment in your file). Vary the original formats if you can, and the type of graph (directed or not). Determine the order (number of nodes) and size (number of edges) of the graphs and visualize them.

Here is a list of servers offering real graph data: