rigraphsna

Bipartite graph projection with nodes as edge attributes


I have a bipartite graph and I want the projections of this graph to have edge attributes that record via which nodes they were connected. For example:

require(igraph)
set.seed(123)
g <- sample_bipartite(5, 5, p =.5)
V(g)$name <- c(letters[1:5], 1:5)
g1 <- bipartite_projection(g)[[1]]
g2 <- bipartite_projection(g)[[2]]

par(mfrow = c(1, 3))
plot(g,
     vertex.shape = ifelse(V(g)$type == FALSE, "square", "circle"),
     vertex.color = ifelse(V(g)$type == FALSE, "gold", "tomato"),
     main = "Bipartite")
plot(g1,
     main = "Projection 1")
plot(g2,
     main = "Projection 2")
par(mfrow = c(1, 1))

enter image description here

I want the information that I added by hand to the plot to be in the network object. It it easily done in igraph? Thanks.


Solution

  • With bipartite_projection

    If you really want ot use bipartite_projection, you can try to define your custom function f like below:

    f <- function(gp) {
      df <- get.data.frame(gp)[1:2]
      df$lbl <- apply(
        df,
        1,
        function(v) {
          max(do.call(intersect, unname(lapply(v, function(x) names(neighbors(g, x))))))
        }
      )
      res <- graph_from_data_frame(df, directed = FALSE)
      plot(res, edge.label = E(res)$lbl)
    }
    
    f(g1)
    f(g2)
    

    which gives

    enter image description here

    enter image description here

    Without bipartite_projection

    Below is an option without using bipartite_projection (take g1 as the an example, and g2 can be obtained in a similar way)

    g1 <- simplify(
      graph_from_data_frame(
        do.call(
          rbind,
          lapply(
            Filter(
              function(x) nrow(x) > 1,
              split(get.data.frame(g), ~to)
            ),
            function(d) {
              with(
                d,
                cbind(data.frame(t(combn(from, 2))), weight = unique(to))
              )
            }
          )
        ),
        directed = FALSE
      ),
      edge.attr.comb = "max"
    )
    

    and plot(g1, edge.label = E(g1)$weight) gives

    enter image description here