# I. Build network

You'll need the below packages:

```{r}
rm(list=ls())
library(igraph) 
```

### 1.1 Create networks
The code below generates an undirected graph with three edges. The numbers are interpreted as vertex IDs, so the edges are 1–>2, 2–>3, 3–>1.

```{r}
g1 <- graph( edges=c(1,2, 2,3, 3, 1), n=3, directed=F ) 

plot(g1) 
g1

```

Now with 10 vertices, and directed by default:

```{r}
# 
g2 <- graph( edges=c(1,2, 2,3, 3, 1), n=10 )

plot(g2)  
```

When the edge list has vertex names, the number of nodes is not needed

```{r}
g3 <- graph( c("John", "Jim", "Jim", "Jill", "Jill", "John")) # named vertices

plot(g3)
```

Small graphs can also be generated with a description of this kind: - for undirected tie, +- or -+ for directed ties pointing left & right, ++ for a symmetric tie, and “:” for sets of vertices.

```{r}
plot(graph_from_literal(a---b, b---c)) # the number of dashes doesn't matter

gl <- graph_from_literal(a-b-c-d-e-f, a-g-h-b, h-e:f:i, j)

plot(gl)

```

### 1.2 Access vertices and edges:
Let us first define a network

```{r}
g4 <- graph( c("John", "Jim", "Jim", "Jack", "Jim", "Jack", "John", "John"), 

             isolates=c("Jesse", "Janis", "Jennifer", "Justin") )  

# In named graphs we can specify isolates by providing a list of their names.



plot(g4, edge.arrow.size=.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) 
```

Access vertices, edges, network matrix:

```{r}
E(g4) # vertex
V(g4) # edge
g4[] # network matrix
```

Add attributes to the network, vertices, or edges:

```{r}
V(g4)$name # automatically generated when we created the network.
```
```{r}
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    # Edge weight, setting all existing edges to 10
```

Examine attributes:

```{r}
edge_attr(g4)
vertex_attr(g4)
```
Plot network by attributes
```{r}
plot(g4, edge.arrow.size=.5, vertex.label.color="black", vertex.label.dist=1.5,

     vertex.color=c( "pink", "skyblue")[1+(V(g4)$gender=="male")] ) 
```
# 2. Network analysis

Here we create the graph that represents the social network of Zachary’s karate club, that shows the friendship between 34 members of a karate club at a US university in the 1970s:

```{r}
net <- make_graph("Zachary")
plot(net)
```

### 2.1 Density
The proportion of present edges from all possible edges in the network.

```{r}
edge_density(net, loops=F)

```

### 2.2 Transitivity

global - ratio of triangles (direction disregarded) to connected triples.
local - ratio of triangles to connected triples each vertex is part of.


```{r}
transitivity(net, type="global")  # net is treated as an undirected network

transitivity(as.undirected(net, mode="collapse")) # same as above

transitivity(net, type="local")

```

### 2.3 Diameter

A network diameter is the longest geodesic distance (length of the shortest path between two nodes) in the network. In igraph, diameter() returns the distance, while get_diameter() returns the nodes along the first found path of that distance.

Note that edge weights are used by default, unless set to NA.
```{r}
diameter(net, directed=F, weights=NA)
diameter(net, directed=F)

diam <- get_diameter(net, directed=T)
diam
```
We can also plot the paths on the diameters
```{r}
vcol <- rep("gray40", vcount(net))

vcol[diam] <- "gold"

ecol <- rep("gray80", ecount(net))

ecol[E(net, path=diam)] <- "orange" 

# E(net, path=diam) finds edges along a path, here 'diam'

plot(net, vertex.color=vcol, edge.color=ecol, edge.arrow.mode=0)
```
### 2.4 Node degrees
The function degree() has a mode of 'in' for in-degree, 'out' for out-degree, and 'all' or 'total' for total degree.

```{r}
deg <- degree(net, mode="all")

plot(net, vertex.size=deg*3)

hist(deg, breaks=1:vcount(net)-1, main="Histogram of node degree")
```
### 2.5 Degree distribution
```{r}
deg.dist <- degree_distribution(net, cumulative=T, mode="all")

plot( x=0:max(deg), y=1-deg.dist, pch=19, cex=1.2, col="orange", 

      xlab="Degree", ylab="Cumulative Frequency")
```

### 2.6 Centrality

Centrality functions (vertex level) and centralization functions (graph level). The centralization functions return res - vertex centrality, centralization, and theoretical_max - maximum centralization score for a graph of that size. The centrality function can run on a subset of nodes (set with the vids parameter). This is helpful for large graphs where calculating all centralities may be a resource-intensive and time-consuming task.
Degree (number of ties)
```{r}
degree(net, mode="in")

centr_degree(net, mode="in", normalized=T)
```

Closeness (centrality based on distance to others in the graph)
Inverse of the node’s average geodesic distance to others in the network.
```{r}
closeness(net, mode="all", weights=NA) 

centr_clo(net, mode="all", normalized=T) 
```
Eigenvector (centrality proportional to the sum of connection centralities)
Values of the first eigenvector of the graph matrix.
```{r}
eigen_centrality(net, directed=T, weights=NA)

centr_eigen(net, directed=T, normalized=T) 
```
Betweenness (centrality based on a broker position connecting others)
Number of geodesics that pass through the node or the edge.
```{r}
betweenness(net, directed=T, weights=NA)

edge_betweenness(net, directed=T, weights=NA)

centr_betw(net, directed=T, normalized=T)
```

### 2.7 Hubs and authorities
The hubs and authorities algorithm developed by Jon Kleinberg was initially used to examine web pages. Hubs were expected to contain catalogs with a large number of outgoing links; while authorities would get many incoming links from hubs, presumably because of their high-quality relevant information.

```{r}
hs <- hub_score(net, weights=NA)$vector

as <- authority_score(net, weights=NA)$vector



par(mfrow=c(1,2))

 plot(net, vertex.size=hs*50, main="Hubs")

 plot(net, vertex.size=as*30, main="Authorities")
```

### 2.8 Distance
Average path length: the mean of the shortest distance between each pair of nodes in the network (in both directions for directed graphs).

```{r}
mean_distance(net, directed=F)
```

# 3. Community detection

### 3.1 Cliques
Find cliques (complete subgraphs of an undirected graph)
```{r}
cliques(net) # list of cliques       

sapply(cliques(net), length) # clique sizes

largest_cliques(net) # cliques with max number of nodes
vcol <- rep("grey80", vcount(net))

vcol[unlist(largest_cliques(net))] <- "gold"

plot(as.undirected(net), vertex.label=V(net)$name, vertex.color=vcol)

```
### 3.2 Community detection
A number of algorithms aim to detect groups that consist of densely connected nodes with fewer connections across groups.

Community detection based on edge betweenness (Newman-Girvan)
High-betweenness edges are removed sequentially (recalculating at each step) and the best partitioning of the network is selected.

```{r}
ceb <- cluster_edge_betweenness(net) 

dendPlot(ceb, mode="hclust")

plot(ceb, net) 
```

Community detection based on based on propagating labels
Assigns node labels, randomizes, than replaces each vertex’s label with the label that appears most frequently among neighbors. Those steps are repeated until each vertex has the most common label of its neighbors.
```{r}
clp <- cluster_label_prop(net)

plot(clp, net)
```

Community detection based on greedy optimization of modularity

```{r}
cfg <- cluster_fast_greedy(as.undirected(net))

plot(cfg, as.undirected(net))

```

