http://kateto.net/networks-r-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
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))

Edge & Vertex Attributes

# 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)

Another way to set attributes

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)

Specific Graphs and Graph Models

eg<- make_empty_graph(40)
plot(eg, vertex.size=10, vertex.label=NA)

Full Graph

fg<-make_full_graph(40)
plot(fg,vertex.size=10, vertex.label= NA)

Simple Star Graph

st<- make_star(40)
plot(st, vertex.size=10, vertex.label=NA)

Tree Graph

tr<- make_tree(40, children = 3, mode= "undirected")
plot(tr, vertex.size=10, vetex.label=NA)

Ring Graph

rn<-make_ring(400)
plot(rn,vertex.size=10, vertex.label=NA)

Erdos-Renyi Random Graph Model

er<- sample_gnm(n=100, m= 40)
plot(er, vertex.size=6 , vertex.label=NA)

Watts-Strogatz small-world model

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.

There is a section on importing and using Social Media Files. Data provided

here is the data

http://www.kateto.net/wordpress/wp-content/uploads/2016/01/netscix2016.zip

nodes <- read.csv("Dataset1-Media-Example-NODES.csv", header=T, as.is=T)

links <- read.csv("Dataset1-Media-Example-EDGES.csv", header=T, as.is=T)

Examine the data

head(nodes)
##    id               media media.type type.label audience.size
## 1 s01            NY Times          1  Newspaper            20
## 2 s02     Washington Post          1  Newspaper            25
## 3 s03 Wall Street Journal          1  Newspaper            30
## 4 s04           USA Today          1  Newspaper            32
## 5 s05            LA Times          1  Newspaper            20
## 6 s06       New York Post          1  Newspaper            50
head(links)
##   from  to weight      type
## 1  s01 s02     10 hyperlink
## 2  s01 s02     12 hyperlink
## 3  s01 s03     22 hyperlink
## 4  s01 s04     21 hyperlink
## 5  s04 s11     22   mention
## 6  s05 s15     21   mention
nrow(nodes); length(unique(nodes$id))
## [1] 17
## [1] 17
nrow(links); nrow(unique(links[,c("from", "to")]))
## [1] 52
## [1] 49

Notice that there are more links than unique from-to combinations. That means we have cases in the data where there are multiple links between the same two nodes. We will collapse all links of the same type between the same two nodes by summing their weights, using aggregate() by “from”, “to”, & “type”. We don’t use simplify() here so as not to collapse different link types.

links <- aggregate(links[,3], links[,-3], sum)

links <- links[order(links$from, links$to),]

colnames(links)[4] <- "weight"

rownames(links) <- NULL

THIS IS JUST WHAT i WANT TO DO

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)

Sometimes, especially with semantic networks, we may be interested in plotting only the labels of the nodes:

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")

plot edge color to match starting node

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) 

5.2 Network layouts

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)

Control layout

plot(net.bg, layout=layout_randomly)

Circular

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)

Circle

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)

Let’s take a look at all available layouts in igraph:

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) 

5.3 Improving network plots

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) 

Plotting multipole.

Here the data are split side by side.

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")

make sure the plots stay in place

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

5.4 Interactive plotting with tkplot

I skipped this.

5.5 Other ways to represent a network

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) )

Using text as nodes may be helpful at times:

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

6.2 Reciprocity

6.3 Transitivity

6.4 Diameter

6.5 Node degrees

8. Subgroups and communities Cliques

COMMUNITY DETECTION

8.2 Community detection

ceb <- cluster_edge_betweenness(net) 

dendPlot(ceb, mode="hclust")

Network plot detected communities

plot(ceb, net)