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