How to create an igraph object from adjacency list with additional information in R?

395 Views Asked by At

I have quite extensive network data in the form

df <- data.frame(name= c("Sue", "Rob", "Jacob", "Terry"), 
                 f1 = c("Rob", "Sue", "Rob", "Jacob"), 
                 f2 = c(NA, "Terry", "Terry", NA),
                 f3 = c(NA, "Jacob", NA, NA), 
                 bf1 = c(1,1,1,0), 
                 bf2 = c(NA, 1, 0, NA), 
                 bf3 = c(NA, 0, NA, NA) )

where the variables f1 to f3 refer to the friends Sue, Rob, Jacob and Terry have. The variables bf1 to bf3 refer to whether they see them as a best friend.

I would now like to create a graph item with R igraph based on this dataframe and include all information. So far I have:

adj_list <- subset(df, select = c(name, f1:f3))
m <- as.matrix(adj_list)
el1 <- cbind(m[, 1], c(m[, -1]))
el1 <- el1[complete.cases(el1),]
el1[2,] <- as.numeric(factor(c(el1[1,])))
g1 <- graph_from_edgelist(el1)

But I don't know how to get the secondary information into the graph object. Any ideas?

1

There are 1 best solutions below

1
On BEST ANSWER

One approach is to reshape your data to long format.

# Get indices of columns to group together
friendsIndices <- with(dat, grep("^f", names(dat))) # strings beginning with 'f`
bffIndices <- with(dat, grep("^bf", names(dat))) # strings beginning with 'bf`

Reshape

ldat <- reshape(dat, 
                varying=list(friendsIndices, bffIndices),
                direction="long", idvar="name")

# Tidy up long data -
  # remove time column
  # remove rows with `NA`
ldat <- ldat[!is.na(ldat$f1), -match("time", names(ldat))]
ldat
#          name    f1 bf1
# Sue.1     Sue   Rob   1
# Rob.1     Rob   Sue   1
# Jacob.1 Jacob   Rob   1
# Terry.1 Terry Jacob   0
# Rob.2     Rob Terry   1
# Jacob.2 Jacob Terry   0
# Rob.3     Rob Jacob   0

Data can now be read in to igraph

library(igraph)
g <- graph_from_data_frame(ldat)

The bf attribute is stored as in the edge attribute E(g)$bf1. You can then add edge colours or weights when plotting based on this attribute.

plot(g, 
     edge.width=2*(E(g)$bf1+1), 
     edge.color=c("red", "blue")[E(g)$bf1+1],
     edge.curved=TRUE)