Nick Knauer Nick Knauer - 2 months ago 6
R Question

Retrieve 1st Degree Connections and 2nd Degree Connections for All Nodes in Igraph

I have an igraph where I would like to extract all of the 1st degree connections of each node along with the 2nd degree connections. The tables need to be separate though.

Full reproducible code with picture of graph is below:

library(igraph)
library(visNetwork)
B = matrix(
c(1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
nrow=10,
ncol=10)
colnames(B) <- c("Alpha", "Bravo", "Colonel", "Demo", "Egg", "Felix", "Gasoline", "Hurricane", "Indigo", "Jab")
rownames(B) <- c("Alpha", "Bravo", "Colonel", "Demo", "Egg", "Felix", "Gasoline", "Hurricane", "Indigo", "Jab")

g96e = t(B) %*% B

i96e = graph.adjacency(g96e, mode = "undirected", weighted = TRUE, diag=FALSE)
visIgraph(i96e)


enter image description here

I would like my final result to be a dataframe that looks like this:

Node ID 1st Degree Connections
Alpha Gasoline
Bravo Egg
Bravo Hurricane
Colonel Felix
Colonel Indigo
Demo Felix
Demo Gasoline
Demo Jab
Egg Bravo
Felix Colonel
Felix Demo
Felix Hurricane
Felix Indigo
Gasoline Alpha
Gasoline Demo
Gasoline Jab
Hurricane Bravo
Hurricane Felix
Indigo Colonel
Indigo Felix
Jab Demo
Jab Gasoline


And then another dataframe with just 2nd degree connections and ideally showing where the source of the 2nd degree connection from but if that's not possible then just the 2nd degree connection would do.

Node ID 2nd Degree Connections From 1st Degree Connection
Alpha Demo Gasoline
Alpha Jab Gasoline
Bravo Felix Hurricane
Colonel Demo Felix
Colonel Hurricane Felix
Colonel Indigo Felix
Colonel Felix Indigo
Demo Colonel Felix
Demo Hurricane Felix
Demo Indigo Felix
Demo Alpha Gasoline
Demo Jab Gasoline
Demo Gasoline Jab
Egg Hurricane Bravo
Felix Indigo Colonel
Felix Gasoline Demo
Felix Jab Demo
Felix Bravo Hurricane
Felix Colonel Indigo
Gasoline Felix Demo
Gasoline Jab Demo
Gasoline Demo Jab
Hurricane Egg Bravo
Hurricane Colonel Felix
Hurricane Demo Felix
Hurricane Indigo Felix
Indigo Felix Colonel
Indigo Colonel Felix
Indigo Demo Felix
Indigo Hurricane Felix
Jab Felix Demo
Jab Gasoline Demo
Jab Alpha Gasoline
Jab Demo Gasoline


Any help would be great, thanks!

Answer

First Degree connection, by definition, is the other vertice connected to the edges of the graph, so you can just use the get.edgelist() to retrieve all direct connections in the graph object, which is a matrix:

library(igraph); library(dplyr);

edges <- get.edgelist(i96e)
edges

#         [,1]       [,2]       
#  [1,] "Alpha"    "Gasoline" 
#  [2,] "Bravo"    "Egg"      
#  [3,] "Bravo"    "Hurricane"
#  [4,] "Colonel"  "Felix"    
#  [5,] "Colonel"  "Indigo"   
#  [6,] "Demo"     "Felix"    
#  [7,] "Demo"     "Gasoline" 
#  [8,] "Demo"     "Jab"      
#  [9,] "Felix"    "Hurricane"
# [10,] "Felix"    "Indigo"   
# [11,] "Gasoline" "Jab"   

The edge list returns an edge only once for each edge, so if you want the first connection for all vertices, you can switch the from and to column and bind with the original edge matrix and this gives a more convenient first order connection data frame:

edgeDF <- rbind(edges, edges[,c(2,1)]) %>% 
          as.data.frame() %>% 
          setNames(c("NodeId", "FirstConnection"))

edgeDF %>% arrange(NodeId, FirstConnection)
#       NodeId FirstConnection
# 1      Alpha        Gasoline
# 2      Bravo             Egg
# 3      Bravo       Hurricane
# 4    Colonel           Felix
# 5    Colonel          Indigo
# 6       Demo           Felix
# 7       Demo        Gasoline
# 8       Demo             Jab
# 9        Egg           Bravo
# 10     Felix         Colonel
# 11     Felix            Demo
# 12     Felix       Hurricane
# 13     Felix          Indigo
# 14  Gasoline           Alpha
# 15  Gasoline            Demo
# 16  Gasoline             Jab
# 17 Hurricane           Bravo
# 18 Hurricane           Felix
# 19    Indigo         Colonel
# 20    Indigo           Felix
# 21       Jab            Demo
# 22       Jab        Gasoline

The second degree connection is the connection of your first degree connection except that the second degree connection shouldn't be the original node, so you can join the first degree data frame with itself and filter records where second degree connections are equal to the nodes themselves:

SecondCon <- setNames(edgeDF, c("FirstConnection", "SecondConnection")) %>% 
             full_join(edgeDF) %>% filter(NodeId != SecondConnection)

SecondCon %>% arrange(NodeId, FirstConnection, SecondConnection)
#    FirstConnection SecondConnection    NodeId
# 1         Gasoline             Demo     Alpha
# 2         Gasoline              Jab     Alpha
# 3        Hurricane            Felix     Bravo
# 4            Felix             Demo   Colonel
# 5            Felix        Hurricane   Colonel
# 6            Felix           Indigo   Colonel
# 7           Indigo            Felix   Colonel
# 8            Felix          Colonel      Demo
# 9            Felix        Hurricane      Demo
# 10           Felix           Indigo      Demo
# 11        Gasoline            Alpha      Demo
# 12        Gasoline              Jab      Demo
# 13             Jab         Gasoline      Demo
# 14           Bravo        Hurricane       Egg
# 15         Colonel           Indigo     Felix
# 16            Demo         Gasoline     Felix
# 17            Demo              Jab     Felix
# 18       Hurricane            Bravo     Felix
# 19          Indigo          Colonel     Felix
# 20            Demo            Felix  Gasoline
# 21            Demo              Jab  Gasoline
# 22             Jab             Demo  Gasoline
# 23           Bravo              Egg Hurricane
# 24           Felix          Colonel Hurricane
# 25           Felix             Demo Hurricane
# 26           Felix           Indigo Hurricane
# 27         Colonel            Felix    Indigo
# 28           Felix          Colonel    Indigo
# 29           Felix             Demo    Indigo
# 30           Felix        Hurricane    Indigo
# 31            Demo            Felix       Jab
# 32            Demo         Gasoline       Jab
# 33        Gasoline            Alpha       Jab
# 34        Gasoline             Demo       Jab