rigraphweighted-graphstatnet

Centrality Measures in a Weighted Network using Statnet in R


I created a weighted network using both igraph and statnet in R. I am now studying centrality measures of my weighted network using statnet, but the centrality measures I obtain are as if statnet did not take into account the values of my edges. Here is a small example to illustrate my problem, using the degree centrality measure.

I created my network using igraph:

nodes <- data.frame(id=c(1,2,3,4,5))
edges <- data.frame(source=c(1,1,2,2,3),
                    target=c(2,3,3,5,4),
                    weight=c(1,2,1,2,1)) 
library(igraph)
network <- graph_from_data_frame(d=edges, vertices=nodes, directed=FALSE)

Then I needed to use the statnet package so I transformed it the following way

  network_statnet <- asNetwork(network)
  detach("package:igraph", unload=TRUE)
  library(statnet)

Then I wanted to compute the degree centrality, first without taking the edges values into account (degree_unweighted), and then taking the edges values into account (degree_weighted)

degree_unweighted<-degree(network_statnet, gmode="graph", ignore.eval=TRUE)
degree_weighted<-degree(network_statnet, gmode="graph", ignore.eval=FALSE)

But I end up with exaclty the same centrality measures. I do not know why statnet does not take into account the values of my edges when I specify ignore.eval=FALSE. I have the same problem with other centrality measures (betweenness, closeness, eigenvector).


Solution

  • You are right, degree ignores weights regardless of ignore.eval. It is visible in the very first line of degree where we have

    dat <- as.edgelist.sna(dat)
    

    while as.edgelist.sna has a parameter attrname:

    attrname - if x is a network object, the (optional) edge attribute to be used to obtain edge values.

    So degree actually doesn't even seem to try to use any weights. As to fix that, we may redefine this function by adding a possibility to use weights as in

    myDegree <- function (dat, g = 1, nodes = NULL, gmode = "digraph", diag = FALSE, 
              tmaxdev = FALSE, cmode = "freeman", rescale = FALSE, ignore.eval = FALSE, attrname = NULL) 
    {
      dat <- as.edgelist.sna(dat, attrname = attrname)
      if (is.list(dat)) 
        return(sapply(dat[g], degree, g = 1, nodes = nodes, gmode = gmode, 
                      diag = diag, tmaxdev = tmaxdev, cmode = cmode, rescale = rescale))
      n <- attr(dat, "n")
      if (gmode == "graph") 
        cmode <- "indegree"
      if (tmaxdev) {
        if (gmode == "digraph") 
          deg <- switch(cmode, indegree = (n - 1) * (n - 1 + 
                                                       diag), outdegree = (n - 1) * (n - 1 + diag), 
                        freeman = (n - 1) * (2 * (n - 1) - 2 + diag))
        else deg <- switch(cmode, indegree = (n - 1) * (n - 2 + 
                                                          diag), outdegree = (n - 1) * (n - 2 + diag), freeman = (n - 
                                                                                                                    1) * (2 * (n - 1) - 2 + diag))
      }
      else {
        m <- NROW(dat)
        cm <- switch(cmode, indegree = 0, outdegree = 1, freeman = 2)
        if (!(cmode %in% c("indegree", "outdegree", "freeman"))) 
          stop("Unknown cmode in degree.\n")
        deg <- .C("degree_R", as.double(dat), as.integer(m), 
                  as.integer(cm), as.integer(diag), as.integer(ignore.eval), 
                  deg = as.double(rep(0, n)), PACKAGE = "sna", NAOK = TRUE)$deg
        if (rescale) 
          deg <- deg/sum(deg)
        if (!is.null(nodes)) 
          deg <- deg[nodes]
      }
      deg
    }
    

    This then gives

    (degree_unweighted <- myDegree(network_statnet, gmode = "graph", ignore.eval = TRUE))
    # [1] 2 3 3 1 1
    (degree_weighted <- myDegree(network_statnet, gmode = "graph", ignore.eval = FALSE, attrname = "weight"))
    # [1] 3 4 4 1 2
    

    I'm afraid you are going to need the same adjustment for other functions such as betweenness.