challenge_4
Ananya Pujary
Centrality of a Network
Author

Ananya Pujary

Published

March 28, 2023

Describe the Network Data

I’ve chosen to work with the got_like_dislike.csv dataset.

Code
got_like_dislike <-read_csv("../posts/_data/got/got_like_dislike.csv")
Rows: 46 Columns: 49
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr  (3): Current house, Former house, Name
dbl (46): Lysa Arryn, Petyr Baelish, Joffrey Baratheon, Margaery Tyrell, Ren...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Code
got_like_dislike
# A tibble: 46 × 49
   `Current house` `Former house` Name              `Lysa Arryn` `Petyr Baelish`
   <chr>           <chr>          <chr>                    <dbl>           <dbl>
 1 Arryn           Tully          Lysa Arryn                  NA               3
 2 Baelish         <NA>           Petyr Baelish                3              NA
 3 Lannister       Baratheon      Joffrey Baratheon            0              -1
 4 Tyrell          Baratheon      Margaery Tyrell              0               1
 5 Baratheon       <NA>           Renly Baratheon              0              -2
 6 Baratheon       <NA>           Robert Baratheon             2               1
 7 Baratheon       <NA>           Stannis Baratheon            0              -1
 8 Stark           <NA>           Brienne of Tarth             1              -1
 9 Lannister       <NA>           Bronn                        0              -1
10 Lannister       <NA>           Gregor Clegane               0              -1
# ℹ 36 more rows
# ℹ 44 more variables: `Joffrey Baratheon` <dbl>, `Margaery Tyrell` <dbl>,
#   `Renly Baratheon` <dbl>, `Robert Baratheon` <dbl>,
#   `Stannis Baratheon` <dbl>, `Brienne of Tarth` <dbl>, Bronn <dbl>,
#   `Gregor Clegane` <dbl>, `Sandor Clegane` <dbl>, `Xaro Xhoan Daxos` <dbl>,
#   Gendry <dbl>, `Balon Greyjoy` <dbl>, `Theon Greyjoy` <dbl>,
#   `Jaqen H'ghar` <dbl>, Hodor <dbl>, `Khal Drogo` <dbl>, …
Code
got_like_dislike.ig <- graph_from_adjacency_matrix(as.matrix(got_like_dislike[ , - c(1 : 3)]), mode = 'directed', weighted = TRUE)
Code
# number of edges
ecount(got_like_dislike.ig)
[1] 1189
Code
# number of vertices
vcount(got_like_dislike.ig)
[1] 46
Code
# vertex and edge attributes
vertex_attr_names(got_like_dislike.ig)
[1] "name"
Code
edge_attr_names(got_like_dislike.ig)
[1] "weight"
Code
# network features
is_directed(got_like_dislike.ig)
[1] TRUE
Code
is_bipartite(got_like_dislike.ig)
[1] FALSE
Code
is_weighted(got_like_dislike.ig)
[1] TRUE
Code
# dyad census
igraph::dyad.census(got_like_dislike.ig)
$mut
[1] 554

$asym
[1] 35

$null
[1] 446
Code
# triad census
triad_census(got_like_dislike.ig)
 [1] 1780  308 4637    5   11   22  222  285    1    1 3849    8   19   26  537
[16] 3469

This network has 1189 edges and 46 vertices. Its vertex attribute is “name” and edge attribute is “weight”. This is a directed network that is not bipartite and is weighted. The dyad census indicated that there are 554 mutual, 35 asymmetric, and 446 null relationships.

Code
# number of components
igraph::components(got_like_dislike.ig)$no
[1] 1
Code
# size of components
igraph::components(got_like_dislike.ig)$csize 
[1] 46

This network has one major component and that component has 46 nodes.

Making a new dataframe nodes with the in-degree, out-degree, and total degree values:

Code
got_like_dislike.nodes<-data.frame(name=V(got_like_dislike.ig)$name,
    totdegree=igraph::degree(got_like_dislike.ig, loops=FALSE),
    indegree=igraph::degree(got_like_dislike.ig, mode="in", loops=FALSE),
    outdegree=igraph::degree(got_like_dislike.ig, mode="out", loops=FALSE))

head(got_like_dislike.nodes)
                               name totdegree indegree outdegree
Lysa Arryn               Lysa Arryn        38       19        19
Petyr Baelish         Petyr Baelish        50       25        25
Joffrey Baratheon Joffrey Baratheon        77       39        38
Margaery Tyrell     Margaery Tyrell        52       28        24
Renly Baratheon     Renly Baratheon        65       32        33
Robert Baratheon   Robert Baratheon        61       31        30

Centrality

First, I’m calculating the eigenvector centrality of each node and adding them to the got_like_dislike.nodes dataframe:

Code
# calculating eigenvector centrality scores
temp<-centr_eigen(got_like_dislike.ig,directed=T)
names(temp)
[1] "vector"          "value"           "options"         "centralization" 
[5] "theoretical_max"
Code
length(temp$vector)
[1] 46
Code
head(temp$vector)
[1] 0.5205582 0.6903608 1.0000000 0.7698198 0.8582532 0.8079125
Code
temp$centralization
[1] 0.3420564
Code
#add eigenvector centrality to node measures
got_like_dislike.nodes$eigen<-evcent(got_like_dislike.ig)$vector
#arrange descending and return top 5 nodes
arrange(got_like_dislike.nodes, desc(eigen)) %>%
  slice(1:5)
                               name totdegree indegree outdegree     eigen
Robb Stark               Robb Stark        74       37        37 1.0000000
Pyat Pree                 Pyat Pree         6        3         3 0.9305896
Stannis Baratheon Stannis Baratheon        66       33        33 0.9197787
Viserys Targaryen Viserys Targaryen        42       21        21 0.9161455
Eddard Stark           Eddard Stark        56       27        29 0.8969999

Similarly, calculating the Bonacich power centrality and adding them to the nodes dataframe:

Code
# calculating bonacich power centrality for nodes
head(power_centrality(got_like_dislike.ig))
       Lysa Arryn     Petyr Baelish Joffrey Baratheon   Margaery Tyrell 
        0.2311048         0.5088790        -1.6047201         0.1408855 
  Renly Baratheon  Robert Baratheon 
       -0.3614043        -0.7448860 
Code
# add bonachic power centrality to node measures
got_like_dislike.nodes$bonpow<-power_centrality(got_like_dislike.ig)
# arrange descending and return top 5 nodes
arrange(got_like_dislike.nodes, desc(bonpow)) %>%
  slice(1:5)
                               name totdegree indegree outdegree        eigen
Petyr Baelish         Petyr Baelish        50       25        25 0.0008802262
Viserys Targaryen Viserys Targaryen        42       21        21 0.9161454694
Lysa Arryn               Lysa Arryn        38       19        19 0.4027269581
Margaery Tyrell     Margaery Tyrell        52       28        24 0.0000000000
Arya Stark               Arya Stark        65       33        32 0.1176348421
                      bonpow
Petyr Baelish     0.50887898
Viserys Targaryen 0.30764903
Lysa Arryn        0.23110481
Margaery Tyrell   0.14088546
Arya Stark        0.06106321

Calculating the distribution of both centrality measure values:

Code
# distribution of eigenvector centrality scores
hist(table(got_like_dislike.nodes$eigen))

Code
plot(density(got_like_dislike.nodes$eigen))

Code
# distribution of bonacich power centrality scores
hist(table(got_like_dislike.nodes$bonpow))

Code
plot(density(got_like_dislike.nodes$bonpow))

Both measures have a similar distribution of values.

Random Network Comparison

Generating a random network with the same number of edges (1189) and vertices (46):

Code
erdos_renyi.ig <- sample_gnm(46, 1189, directed = TRUE, loops = FALSE)

# density of random network
graph.density(erdos_renyi.ig)
[1] 0.5743961
Code
# dyad census of random network
igraph::dyad.census(erdos_renyi.ig)
$mut
[1] 346

$asym
[1] 497

$null
[1] 192
Code
# triad census of random network
igraph::triad.census(erdos_renyi.ig)
 [1]   85  784  500  486  468  921 1380 1422 1259  431  948  902  849 1754 2452
[16]  539

Creating a nodes dataframe for this network with total degree, in-degree, and out-degree values:

Code
erdos_renyi.nodes<-data.frame(degree=igraph::degree(erdos_renyi.ig))
erdos_renyi.nodes<-erdos_renyi.nodes %>%
    mutate(indegree=igraph::degree(erdos_renyi.ig, mode="in", loops=FALSE),
           outdegree=igraph::degree(erdos_renyi.ig, mode="out", loops=FALSE))
head(erdos_renyi.nodes)
  degree indegree outdegree
1     43       17        26
2     61       26        35
3     61       31        30
4     52       29        23
5     52       29        23
6     52       23        29

First, I’m calculating the eigenvector centrality of each node and adding them to the got_like_dislike.nodes dataframe:

Code
# calculating eigenvector centrality scores
temp<-centr_eigen(erdos_renyi.ig,directed=T)
names(temp)
[1] "vector"          "value"           "options"         "centralization" 
[5] "theoretical_max"
Code
length(temp$vector)
[1] 46
Code
head(temp$vector)
[1] 0.5471242 0.8163483 0.9904156 0.8971429 0.8923585 0.7332920
Code
temp$centralization
[1] 0.197041
Code
#add eigenvector centrality to node measures
erdos_renyi.nodes$eigen<-evcent(erdos_renyi.ig)$vector
#arrange descending and return top 5 nodes
arrange(erdos_renyi.nodes, desc(eigen)) %>%
  slice(1:5)
  degree indegree outdegree     eigen
1     61       31        30 1.0000000
2     61       26        35 0.9894859
3     59       32        27 0.9601890
4     58       31        27 0.9473595
5     58       27        31 0.9447701

Similarly, calculating the Bonacich power centrality and adding them to the nodes dataframe:

Code
# calculating bonacich power centrality for nodes
head(power_centrality(erdos_renyi.ig))
[1] -0.9924564 -0.9058985 -1.2946816 -0.9157178 -1.1668815 -1.1708260
Code
# add bonachic power centrality to node measures
erdos_renyi.nodes$bonpow<-power_centrality(erdos_renyi.ig)
# arrange descending and return top 5 nodes
arrange(erdos_renyi.nodes, desc(bonpow)) %>%
  slice(1:5)
  degree indegree outdegree     eigen     bonpow
1     53       29        24 0.8705401 -0.5578755
2     47       24        23 0.7681401 -0.5993879
3     46       23        23 0.7620806 -0.7157912
4     54       28        26 0.8872706 -0.7894939
5     52       28        24 0.8554152 -0.7986151

Calculating the distribution of both centrality measure values:

Code
table(erdos_renyi.nodes$eigen)

0.710459524483067 0.730773737248582 0.762080618679934 0.763854446274567 
                1                 1                 1                 1 
0.768140052215201 0.775694826757958 0.783787341726523 0.784700320387665 
                1                 1                 1                 1 
 0.79141086769108 0.795424162226855   0.7964332642134 0.799432647857085 
                1                 1                 1                 1 
0.801651628621503 0.802985710724236  0.81345162285852 0.816334621848167 
                1                 1                 1                 1 
0.821944712043148 0.826625564944117 0.832781505482511  0.83380715230376 
                1                 1                 1                 1 
0.836159855792579 0.837575593087785 0.848475224417039  0.85076562676721 
                1                 1                 1                 1 
0.852580324727284 0.855125215140171 0.855415234648243 0.855708262663948 
                1                 1                 1                 1 
0.860542251613786 0.861101305850915 0.862734161327381 0.867516644283842 
                1                 1                 1                 1 
0.870540141274848 0.873990581409109 0.876885728746854 0.878176339549181 
                1                 1                 1                 1 
0.887270618631575 0.887946065936564 0.891205712117302 0.915697440881502 
                1                 1                 1                 1 
0.919469563194441 0.944770097330143 0.947359538574922 0.960189011205497 
                1                 1                 1                 1 
0.989485943747128                 1 
                1                 1 
Code
# distribution of eigenvector centrality density scores
plot(density(erdos_renyi.nodes$eigen))

Code
table(erdos_renyi.nodes$bonpow)

 -1.32490952447138  -1.29468156788833  -1.28834974241691  -1.21448112454971 
                 1                  1                  1                  1 
 -1.17728714785492  -1.17082602103025   -1.1689896561108  -1.16688154272432 
                 1                  1                  1                  1 
 -1.14062398554819  -1.11316699858162  -1.10529933805968  -1.07551193248265 
                 1                  1                  1                  1 
  -1.0609220796921  -1.05162411027476  -1.05036322151678  -1.04226466387798 
                 1                  1                  1                  1 
 -1.04174313839012  -1.03770717937863  -1.03643801888203  -1.03050297334381 
                 1                  1                  1                  1 
 -1.02577952110278  -1.02247064440326  -1.01849163664304 -0.998740001730098 
                 1                  1                  1                  1 
-0.998289804857671 -0.993260939917644 -0.992456390480723 -0.975268672125168 
                 1                  1                  1                  1 
 -0.92468861466528 -0.915717775843969 -0.908925705598518 -0.905898486753508 
                 1                  1                  1                  1 
 -0.88553150384365 -0.885011864653844  -0.87596546447822  -0.86198148814366 
                 1                  1                  1                  1 
-0.834478423892282 -0.834023981010559 -0.827883694226589 -0.817608114431377 
                 1                  1                  1                  1 
-0.806943589798597 -0.798615110646334 -0.789493864739947 -0.715791168664969 
                 1                  1                  1                  1 
-0.599387899552842 -0.557875459245137 
                 1                  1 
Code
# distribution of bonacich power centrality density scores
plot(density(erdos_renyi.nodes$bonpow))

Comparing the density distribution of eigenvector centrality scores in the like-dislike network and the random network, there’s a right skew in the like-dislike network while the scores are normally distributed in the random network. As for the Bonacich power centrality scores, they are similarly distributed in both networks.