library(igraph)
##
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union
g1<- graph(edges = c(1,2,2,3,3,1), n= 3, directed = F)
plot(g1)
class(g1)
## [1] "igraph"
#now with 10 vertices, directed by default
g2<- graph(edges = c(1,2,2,3,3,1) , n= 10)
plot(g2)
g3<-graph(c("John","Jim","Jim","Jill","Jill","John"))
plot(g3)
g4 <- graph(c("John","Jim","Jim","Jack","Jim","Jack","John","John"),
isolates=c("Jesse","Janis","Jennifer","Justin"))
plot(g4, edge.arrow.size=0.5, vertex.color="gold",vertex.size=15,
vertex.frame.color="gray",vertex.label.color="black",
vertex.label.cex=0.8, vertex.label.dist=2, edge.curved=0.2)
#small graphs
plot(graph_from_literal(a -- b , b --c ))# # of dashes doesnt matter
plot(graph_from_literal(a+B,b++c))
plot(graph_from_literal(a+b,b++c))
# the edges of the object
E(g4)
## + 4/4 edges from 556e1cb (vertex names):
## [1] John->Jim Jim ->Jack Jim ->Jack John->John
#the vertices of the object
V(g4)
## + 7/7 vertices, named, from 556e1cb:
## [1] John Jim Jack Jesse Janis Jennifer Justin
g4[] #examine the matrix
## 7 x 7 sparse Matrix of class "dgCMatrix"
## John Jim Jack Jesse Janis Jennifer Justin
## John 1 1 . . . . .
## Jim . . 2 . . . .
## Jack . . . . . . .
## Jesse . . . . . . .
## Janis . . . . . . .
## Jennifer . . . . . . .
## Justin . . . . . . .
g4[1,]
## John Jim Jack Jesse Janis Jennifer Justin
## 1 1 0 0 0 0 0
V(g4)$name
## [1] "John" "Jim" "Jack" "Jesse" "Janis" "Jennifer"
## [7] "Justin"
V(g4)$gender <- c("male","male","male","male","female","female","male")
E(g4)$type<- "email" # Edge attribute, assign "email" to all edges
E(g4)#weight<-10
## + 4/4 edges from 556e1cb (vertex names):
## [1] John->Jim Jim ->Jack Jim ->Jack John->John
# Edge weight, all edges
plot(g4)
g4<- set_graph_attr(g4,"name","Email Network")
g4<- set_graph_attr(g4, "something" , "A thing")
graph_attr_names(g4)
## [1] "name" "something"
graph_attr(g4,"name")
## [1] "Email Network"
graph_attr(g4)
## $name
## [1] "Email Network"
##
## $something
## [1] "A thing"
# delete attribute
g4<- delete_graph_attr(g4, "something")
graph_attr(g4)
## $name
## [1] "Email Network"
plot(g4,edge.arrow.size= 0.5, vertex.label.color= "black", vertex.label.dist= 1.5, vertex.color=c("pink","skyblue")[1+(V(g4)$gender=="male")])
plot(g4,edge.arrow.size= 2, vertex.label.color= "green", vertex.label.dist= 3, vertex.color=c("pink","skyblue")[1+(V(g4)$gender=="male")])
we can simplify graph and remove loops and multi arrows with edge.attr.comb. options: sum,mean,prod,min,max,first/last or “ignore” g4s <- simplify( g4, remove.multiple = T, remove.loops = F,
edge.attr.comb=c(weight="sum", type="ignore") )
plot(g4s, vertex.label.dist=1.5)
eg<- make_empty_graph(40)
plot(eg, vertex.size=10, vertex.label=NA)
fg<-make_full_graph(40)
plot(fg,vertex.size=10, vertex.label= NA)
st<- make_star(40)
plot(st, vertex.size=10, vertex.label=NA)
tr<- make_tree(40, children = 3, mode= "undirected")
plot(tr, vertex.size=10, vetex.label=NA)
rn<-make_ring(400)
plot(rn,vertex.size=10, vertex.label=NA)
er<- sample_gnm(n=100, m= 40)
plot(er, vertex.size=6 , vertex.label=NA)
sw <- sample_smallworld(dim=2, size=10, nei=1, p=0.1)
plot(sw, vertex.size=6, vertex.label=NA, layout=layout_in_circle)
## There are many, many kinds of graphs. See link.
nodes2 <- read.csv("Dataset2-Media-User-Example-NODES.csv", header=T, as.is=T)
links2 <- read.csv("Dataset2-Media-User-Example-EDGES.csv", header=T, row.names=1)
Examine the data
head(nodes2)
## id media media.type media.name audience.size
## 1 s01 NYT 1 Newspaper 20
## 2 s02 WaPo 1 Newspaper 25
## 3 s03 WSJ 1 Newspaper 30
## 4 s04 USAT 1 Newspaper 32
## 5 s05 LATimes 1 Newspaper 20
## 6 s06 CNN 2 TV 56
head(links2)
## U01 U02 U03 U04 U05 U06 U07 U08 U09 U10 U11 U12 U13 U14 U15 U16 U17
## s01 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## s02 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
## s03 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0
## s04 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0
## s05 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
## s06 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1
## U18 U19 U20
## s01 0 0 0
## s02 0 0 1
## s03 0 0 0
## s04 0 0 0
## s05 0 0 0
## s06 0 0 0
We can see that links2 is an adjacency matrix for a two-mode network:
links2 <- as.matrix(links2)
dim(links2)
## [1] 10 20
dim(nodes2)
## [1] 30 5
We start by converting the raw data to an igraph network object. Here we use igraph’s graph.data.frame function, which takes two data frames: d and vertices.
d describes the edges of the network. Its first two columns are the IDs of the source and the target node for each edge. The following columns are edge attributes (weight, type, label, or anything else). vertices starts with a column of node IDs. Any following columns are interpreted as node attributes.
library(igraph)
net <- graph_from_data_frame(d=links, vertices=nodes, directed=T)
class(net)
## [1] "igraph"
net
## IGRAPH 584921d DNW- 17 49 --
## + attr: name (v/c), media (v/c), media.type (v/n), type.label
## | (v/c), audience.size (v/n), type (e/c), weight (e/n)
## + edges from 584921d (vertex names):
## [1] s01->s02 s01->s03 s01->s04 s01->s15 s02->s01 s02->s03 s02->s09
## [8] s02->s10 s03->s01 s03->s04 s03->s05 s03->s08 s03->s10 s03->s11
## [15] s03->s12 s04->s03 s04->s06 s04->s11 s04->s12 s04->s17 s05->s01
## [22] s05->s02 s05->s09 s05->s15 s06->s06 s06->s16 s06->s17 s07->s03
## [29] s07->s08 s07->s10 s07->s14 s08->s03 s08->s07 s08->s09 s09->s10
## [36] s10->s03 s12->s06 s12->s13 s12->s14 s13->s12 s13->s17 s14->s11
## [43] s14->s13 s15->s01 s15->s04 s15->s06 s16->s06 s16->s17 s17->s04
We also have easy access to nodes, edges, and their attributes with:
E(net) # The edges of the "net" object
## + 49/49 edges from 584921d (vertex names):
## [1] s01->s02 s01->s03 s01->s04 s01->s15 s02->s01 s02->s03 s02->s09
## [8] s02->s10 s03->s01 s03->s04 s03->s05 s03->s08 s03->s10 s03->s11
## [15] s03->s12 s04->s03 s04->s06 s04->s11 s04->s12 s04->s17 s05->s01
## [22] s05->s02 s05->s09 s05->s15 s06->s06 s06->s16 s06->s17 s07->s03
## [29] s07->s08 s07->s10 s07->s14 s08->s03 s08->s07 s08->s09 s09->s10
## [36] s10->s03 s12->s06 s12->s13 s12->s14 s13->s12 s13->s17 s14->s11
## [43] s14->s13 s15->s01 s15->s04 s15->s06 s16->s06 s16->s17 s17->s04
V(net) # The vertices of the "net" object
## + 17/17 vertices, named, from 584921d:
## [1] s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 s13 s14 s15 s16 s17
E(net)$type # Edge attribute "type"
## [1] "hyperlink" "hyperlink" "hyperlink" "mention" "hyperlink"
## [6] "hyperlink" "hyperlink" "hyperlink" "hyperlink" "hyperlink"
## [11] "hyperlink" "hyperlink" "mention" "hyperlink" "hyperlink"
## [16] "hyperlink" "mention" "mention" "hyperlink" "mention"
## [21] "mention" "hyperlink" "hyperlink" "mention" "hyperlink"
## [26] "hyperlink" "mention" "mention" "mention" "hyperlink"
## [31] "mention" "hyperlink" "mention" "mention" "mention"
## [36] "hyperlink" "mention" "hyperlink" "mention" "hyperlink"
## [41] "mention" "mention" "mention" "hyperlink" "hyperlink"
## [46] "hyperlink" "hyperlink" "mention" "hyperlink"
V(net)$media # Vertex attribute "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"
Now that we have our igraph network object, let’s make a first attempt to plot it.
plot(net, edge.arrow.size=.4,vertex.label=NA)
That doesn’t look very good. Let’s start fixing things by removing the loops in the graph.
net <- simplify(net, remove.multiple = F, remove.loops = T)
You can extract the edge list or matrix
as_edgelist(net, names=T)
## [,1] [,2]
## [1,] "s01" "s02"
## [2,] "s01" "s03"
## [3,] "s01" "s04"
## [4,] "s01" "s15"
## [5,] "s02" "s01"
## [6,] "s02" "s03"
## [7,] "s02" "s09"
## [8,] "s02" "s10"
## [9,] "s03" "s01"
## [10,] "s03" "s04"
## [11,] "s03" "s05"
## [12,] "s03" "s08"
## [13,] "s03" "s10"
## [14,] "s03" "s11"
## [15,] "s03" "s12"
## [16,] "s04" "s03"
## [17,] "s04" "s06"
## [18,] "s04" "s11"
## [19,] "s04" "s12"
## [20,] "s04" "s17"
## [21,] "s05" "s01"
## [22,] "s05" "s02"
## [23,] "s05" "s09"
## [24,] "s05" "s15"
## [25,] "s06" "s16"
## [26,] "s06" "s17"
## [27,] "s07" "s03"
## [28,] "s07" "s08"
## [29,] "s07" "s10"
## [30,] "s07" "s14"
## [31,] "s08" "s03"
## [32,] "s08" "s07"
## [33,] "s08" "s09"
## [34,] "s09" "s10"
## [35,] "s10" "s03"
## [36,] "s12" "s06"
## [37,] "s12" "s13"
## [38,] "s12" "s14"
## [39,] "s13" "s12"
## [40,] "s13" "s17"
## [41,] "s14" "s11"
## [42,] "s14" "s13"
## [43,] "s15" "s01"
## [44,] "s15" "s04"
## [45,] "s15" "s06"
## [46,] "s16" "s06"
## [47,] "s16" "s17"
## [48,] "s17" "s04"
as_adjacency_matrix(net, attr="weight")
## 17 x 17 sparse Matrix of class "dgCMatrix"
## [[ suppressing 17 column names 's01', 's02', 's03' ... ]]
##
## s01 . 22 22 21 . . . . . . . . . . 20 . .
## s02 23 . 21 . . . . . 1 5 . . . . . . .
## s03 21 . . 22 1 . . 4 . 2 1 1 . . . . .
## s04 . . 23 . . 1 . . . . 22 3 . . . . 2
## s05 1 21 . . . . . . 2 . . . . . 21 . .
## s06 . . . . . . . . . . . . . . . 21 21
## s07 . . 1 . . . . 22 . 21 . . . 4 . . .
## s08 . . 2 . . . 21 . 23 . . . . . . . .
## s09 . . . . . . . . . 21 . . . . . . .
## s10 . . 2 . . . . . . . . . . . . . .
## s11 . . . . . . . . . . . . . . . . .
## s12 . . . . . 2 . . . . . . 22 22 . . .
## s13 . . . . . . . . . . . 21 . . . . 1
## s14 . . . . . . . . . . 1 . 21 . . . .
## s15 22 . . 1 . 4 . . . . . . . . . . .
## s16 . . . . . 23 . . . . . . . . . . 21
## s17 . . . 4 . . . . . . . . . . . . .
Or data frames describing nodes and edges:
as_data_frame(net, what="edges")
## from to type weight
## 1 s01 s02 hyperlink 22
## 2 s01 s03 hyperlink 22
## 3 s01 s04 hyperlink 21
## 4 s01 s15 mention 20
## 5 s02 s01 hyperlink 23
## 6 s02 s03 hyperlink 21
## 7 s02 s09 hyperlink 1
## 8 s02 s10 hyperlink 5
## 9 s03 s01 hyperlink 21
## 10 s03 s04 hyperlink 22
## 11 s03 s05 hyperlink 1
## 12 s03 s08 hyperlink 4
## 13 s03 s10 mention 2
## 14 s03 s11 hyperlink 1
## 15 s03 s12 hyperlink 1
## 16 s04 s03 hyperlink 23
## 17 s04 s06 mention 1
## 18 s04 s11 mention 22
## 19 s04 s12 hyperlink 3
## 20 s04 s17 mention 2
## 21 s05 s01 mention 1
## 22 s05 s02 hyperlink 21
## 23 s05 s09 hyperlink 2
## 24 s05 s15 mention 21
## 25 s06 s16 hyperlink 21
## 26 s06 s17 mention 21
## 27 s07 s03 mention 1
## 28 s07 s08 mention 22
## 29 s07 s10 hyperlink 21
## 30 s07 s14 mention 4
## 31 s08 s03 hyperlink 2
## 32 s08 s07 mention 21
## 33 s08 s09 mention 23
## 34 s09 s10 mention 21
## 35 s10 s03 hyperlink 2
## 36 s12 s06 mention 2
## 37 s12 s13 hyperlink 22
## 38 s12 s14 mention 22
## 39 s13 s12 hyperlink 21
## 40 s13 s17 mention 1
## 41 s14 s11 mention 1
## 42 s14 s13 mention 21
## 43 s15 s01 hyperlink 22
## 44 s15 s04 hyperlink 1
## 45 s15 s06 hyperlink 4
## 46 s16 s06 hyperlink 23
## 47 s16 s17 mention 21
## 48 s17 s04 hyperlink 4
as_data_frame(net, what="vertices")
## name media media.type type.label audience.size
## s01 s01 NY Times 1 Newspaper 20
## s02 s02 Washington Post 1 Newspaper 25
## s03 s03 Wall Street Journal 1 Newspaper 30
## s04 s04 USA Today 1 Newspaper 32
## s05 s05 LA Times 1 Newspaper 20
## s06 s06 New York Post 1 Newspaper 50
## s07 s07 CNN 2 TV 56
## s08 s08 MSNBC 2 TV 34
## s09 s09 FOX News 2 TV 60
## s10 s10 ABC 2 TV 23
## s11 s11 BBC 2 TV 34
## s12 s12 Yahoo News 3 Online 33
## s13 s13 Google News 3 Online 23
## s14 s14 Reuters.com 3 Online 12
## s15 s15 NYTimes.com 3 Online 24
## s16 s16 WashingtonPost.com 3 Online 28
## s17 s17 AOL.com 3 Online 33
As we have seen above, this time the edges of the network are in a matrix format. We can read those into a graph object using graph_from_incidence_matrix()
head(nodes2)
## id media media.type media.name audience.size
## 1 s01 NYT 1 Newspaper 20
## 2 s02 WaPo 1 Newspaper 25
## 3 s03 WSJ 1 Newspaper 30
## 4 s04 USAT 1 Newspaper 32
## 5 s05 LATimes 1 Newspaper 20
## 6 s06 CNN 2 TV 56
head(links2)
## U01 U02 U03 U04 U05 U06 U07 U08 U09 U10 U11 U12 U13 U14 U15 U16 U17
## s01 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## s02 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
## s03 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0
## s04 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0
## s05 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
## s06 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1
## U18 U19 U20
## s01 0 0 0
## s02 0 0 1
## s03 0 0 0
## s04 0 0 0
## s05 0 0 0
## s06 0 0 0
net2<- graph_from_incidence_matrix(links2)
table(V(net2)$type)
##
## FALSE TRUE
## 10 20
To transform a one-mode network matrix into an igraph object, use instead graph_from_adjacency_matrix().
net2.bp <- bipartite.projection(net2)
We can calculate the projections manually as well:
as_incidence_matrix(net2) %*% t(as_incidence_matrix(net2))
## s01 s02 s03 s04 s05 s06 s07 s08 s09 s10
## s01 3 0 0 0 0 0 0 0 0 1
## s02 0 3 0 0 0 0 0 0 1 0
## s03 0 0 4 1 0 0 0 0 1 0
## s04 0 0 1 3 1 0 0 0 0 1
## s05 0 0 0 1 3 1 0 0 0 1
## s06 0 0 0 0 1 3 1 1 0 0
## s07 0 0 0 0 0 1 3 1 0 0
## s08 0 0 0 0 0 1 1 4 1 0
## s09 0 1 1 0 0 0 0 1 3 0
## s10 1 0 0 1 1 0 0 0 0 2
t(as_incidence_matrix(net2)) %*% as_incidence_matrix(net2)
## U01 U02 U03 U04 U05 U06 U07 U08 U09 U10 U11 U12 U13 U14 U15 U16 U17
## U01 2 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0
## U02 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## U03 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## U04 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
## U05 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
## U06 0 0 0 0 0 2 1 1 1 0 0 0 0 0 0 0 0
## U07 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0
## U08 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0
## U09 0 0 0 0 0 1 1 1 2 1 1 0 0 0 0 0 0
## U10 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0
## U11 1 0 0 0 0 0 0 0 1 1 3 1 1 0 0 0 0
## U12 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
## U13 0 0 0 0 0 0 0 0 0 0 1 1 2 1 0 0 1
## U14 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 1
## U15 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0
## U16 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 1
## U17 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 2
## U18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
## U19 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1
## U20 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0
## U18 U19 U20
## U01 0 0 0
## U02 0 0 0
## U03 0 0 0
## U04 0 0 1
## U05 0 0 1
## U06 0 1 1
## U07 0 0 0
## U08 0 0 0
## U09 0 0 0
## U10 0 0 0
## U11 0 0 0
## U12 0 0 0
## U13 0 0 0
## U14 0 0 0
## U15 0 0 0
## U16 1 1 0
## U17 1 1 0
## U18 1 1 0
## U19 1 2 1
## U20 0 1 2
plot(net2.bp$proj1, vertex.label.color="black", vertex.label.dist=1,
vertex.size=7, vertex.label=nodes2$media[!is.na(nodes2$media.type)])
plot(net2.bp$proj2, vertex.label.color="black", vertex.label.dist=1,
vertex.size=7, vertex.label=nodes2$media[ is.na(nodes2$media.type)])
I graph plotting parameters partial list: NODES
vertex.color Node color vertex.frame.color Node border color vertex.shape One of “none”, “circle”, “square”, “csquare”, “rectangle” “crectangle”, “vrectangle”, “pie”, “raster”, or “sphere” vertex.size Size of the node (default is 15) vertex.size2 The second size of the node (e.g. for a rectangle) vertex.label Character vector used to label the nodes vertex.label.family Font family of the label (e.g.“Times”, “Helvetica”) vertex.label.font Font: 1 plain, 2 bold, 3, italic, 4 bold italic, 5 symbol vertex.label.cex Font size (multiplication factor, device-dependent) vertex.label.dist Distance between the label and the vertex vertex.label.degree The position of the label in relation to the vertex, where 0 right, “pi” is left, “pi/2” is below, and “-pi/2” is above EDGES
edge.color Edge color edge.width Edge width, defaults to 1 edge.arrow.size Arrow size, defaults to 1 edge.arrow.width Arrow width, defaults to 1 edge.lty Line type, could be 0 or “blank”, 1 or “solid”, 2 or “dashed”, 3 or “dotted”, 4 or “dotdash”, 5 or “longdash”, 6 or “twodash” edge.label Character vector used to label edges edge.label.family Font family of the label (e.g.“Times”, “Helvetica”) edge.label.font Font: 1 plain, 2 bold, 3, italic, 4 bold italic, 5 symbol edge.label.cex Font size for edge labels edge.curved Edge curvature, range 0-1 (FALSE sets it to 0, TRUE to 0.5) arrow.mode Vector specifying whether edges should have arrows, possible values: 0 no arrow, 1 back, 2 forward, 3 both OTHER
margin Empty space margins around the plot, vector with length 4 frame if TRUE, the plot will be framed main If set, adds a title to the plot sub If set, adds a subtitle to the plot
We can set the node & edge options in two ways - the first one is to specify them in the plot() function, as we are doing below.
# Plot with curved edges (edge.curved=.1) and reduce arrow size:
plot(net, edge.arrow.size=.4, edge.curved=.1)
# Set edge color to gray, and the node color to orange.
# Replace the vertex label with the node names stored in "media"
plot(net, edge.arrow.size=.2, edge.curved=0,
vertex.color="orange", vertex.frame.color="#555555",
vertex.label=V(net)$media, vertex.label.color="black",
vertex.label.cex=.7)
The second way to set attributes is to add them to the igraph object. Let’s say we want to color our network nodes based on type of media, and size them based on audience size (larger audience -> larger node). We will also change the width of the edges based on their weight.
# Generate colors based on media type:
colrs <- c("gray50", "tomato", "gold")
V(net)$color <- colrs[V(net)$media.type]
# Set node size based on audience size:
V(net)$size <- V(net)$audience.size*0.7
# The labels are currently node IDs.
# Setting them to NA will render no labels:
V(net)$label.color <- "black"
V(net)$label <- NA
# Set edge width based on weight:
E(net)$width <- E(net)$weight/6
#change arrow size and edge color:
E(net)$arrow.size <- .2
E(net)$edge.color <- "gray80"
E(net)$width <- 1+E(net)$weight/12
plot(net)
We can also override the attributes explicitly in the plot:
plot(net, edge.color="orange", vertex.color="gray50")
It helps to add a legend explaining the meaning of the colors we used:
plot(net)
legend(x=-1.5, y=-1.1, c("Newspaper","Television", "Online News"), pch=21,
col="#777777", pt.bg=colrs, pt.cex=2, cex=.8, bty="n", ncol=1)
plot(net, vertex.shape="none", vertex.label=V(net)$media,
vertex.label.font=2, vertex.label.color="gray40",
vertex.label.cex=.7, edge.color="gray85")
edge.start <- ends(net, es=E(net), names=F)[,1]
edge.col <- V(net)$color[edge.start]
plot(net, edge.color=edge.col, edge.curved=.1)
We use the sample_pa() function which generates a simple graph starting from one node and adding more nodes and links based on a preset level of preferential attachment (Barabasi-Albert model).
net.bg <- sample_pa(80)
V(net.bg)$size <- 8
V(net.bg)$frame.color <- "white"
V(net.bg)$color <- "orange"
V(net.bg)$label <- ""
E(net.bg)$arrow.mode <- 0
plot(net.bg)
plot(net.bg, layout=layout_randomly)
l <- layout_in_circle(net.bg)
plot(net.bg, layout=l)
l <- cbind(1:vcount(net.bg), c(1, vcount(net.bg):2))
plot(net.bg, layout=l)
l <- layout_in_circle(net.bg)
plot(net.bg, layout=l)
Sphere
l <- layout_on_sphere(net.bg)
plot(net.bg, layout=l)
Fruchterman-Reingold is one of the most used force-directed layout algorithms out there.
Force-directed layouts try to get a nice-looking graph where edges are similar in length and cross each other as little as possible. They simulate the graph as a physical system. Nodes are electrically charged particles that repulse each other when they get too close. The edges act as springs that attract connected nodes closer together. As a result, nodes are evenly distributed through the chart area, and the layout is intuitive in that nodes which share more connections are closer to each other. The disadvantage of these algorithms is that they are rather slow and therefore less often used in graphs larger than ~1000 vertices. You can set the “weight” parameter which increases the attraction forces among nodes connected by heavier edges.
l <- layout_with_fr(net.bg)
plot(net.bg, layout=l)
Another popular force-directed algorithm that produces nice results for connected graphs is Kamada Kawai. Like Fruchterman Reingold, it attempts to minimize the energy in a spring system.
l <- layout_with_kk(net.bg)
plot(net.bg, layout=l)
layouts <- grep("^layout_", ls("package:igraph"), value=TRUE)[-1]
# Remove layouts that do not apply to our graph.
layouts <- layouts[!grepl("bipartite|merge|norm|sugiyama|tree", layouts)]
par(mfrow=c(3,3), mar=c(1,1,1,1))
for (layout in layouts) {
print(layout)
l <- do.call(layout, list(net))
plot(net, edge.arrow.mode=0, layout=l, main=layout) }
## [1] "layout_as_star"
## [1] "layout_components"
## [1] "layout_in_circle"
## [1] "layout_nicely"
## [1] "layout_on_grid"
## [1] "layout_on_sphere"
## [1] "layout_randomly"
## [1] "layout_with_dh"
## [1] "layout_with_drl"
## [1] "layout_with_fr"
## [1] "layout_with_gem"
## [1] "layout_with_graphopt"
## [1] "layout_with_kk"
## [1] "layout_with_lgl"
## [1] "layout_with_mds"
There are more sophisticated ways to extract the key edges, but for the purposes of this exercise we’ll only keep ones that have weight higher than the mean for the network. In igraph, we can delete edges using delete_edges(net, edges):
cut.off <- mean(links$weight)
net.sp <- delete_edges(net, E(net)[weight<cut.off])
plot(net.sp)
Notice that our network plot is still not too helpful. We can identify the type and size of nodes, but cannot see much about the structure since the links we’re examining are so dense. One way to approach this is to see if we can sparsify the network, keeping only the most important ties and discarding the rest.
There are more sophisticated ways to extract the key edges, but for the purposes of this exercise we’ll only keep ones that have weight higher than the mean for the network. In igraph, we can delete edges using delete_edges(net, edges):
hist(links$weight)
mean(links$weight)
## [1] 12.40816
sd(links$weight)
## [1] 9.905635
cut.off <- mean(links$weight)
net.sp <- delete_edges(net, E(net)[weight<cut.off])
# Above drops Edgeswhose weight is < mean.
plot(net.sp)
net.m <- net - E(net)[E(net)$type=="hyperlink"] # another way to delete edges
net.h <- net - E(net)[E(net)$type=="mention"]
# Plot the two links separately:
par(mfrow=c(1,2))
plot(net.h, vertex.color="orange", main="Tie: Hyperlink")
plot(net.m, vertex.color="lightsteelblue2", main="Tie: Mention")
l <- layout_with_fr(net)
plot(net.h, vertex.color="orange", layout=l, main="Tie: Hyperlink")
plot(net.m, vertex.color="lightsteelblue2", layout=l, main="Tie: Mention")
# in a seperate cell after the graph:
dev.off()
## null device
## 1
I skipped this.
For example, here is a quick heatmap of the network matrix:
netm <- get.adjacency(net, attr="weight", sparse=F)
colnames(netm) <- V(net)$media
rownames(netm) <- V(net)$media
palf <- colorRampPalette(c("gold", "dark orange"))
heatmap(netm[,17:1], Rowv = NA, Colv = NA, col = palf(100),
scale="none", margins=c(10,10) )
plot(net2, vertex.shape="none", vertex.label=nodes2$media,
vertex.label.color=V(net2)$color, vertex.label.font=2.5,
vertex.label.cex=.6, edge.color="gray70", edge.width=2)
#### 6.Network and node descriptives 6.1 Density
ceb <- cluster_edge_betweenness(net)
dendPlot(ceb, mode="hclust")
plot(ceb, net)