【问题标题】:bipartite projection without the intermediate bipartite graph没有中间二分图的二分投影
【发布时间】:2013-04-06 17:18:07
【问题描述】:

我有一个data.frame,它描述了一个具有非常大(数百万)和相当小的(数百)独立集合的二分图。

我想在较小的独立集上获得图的二分投影,但没有首先创建大型二分图,尤其是对较大独立集的巨大二分投影。这种限制的原因是igraph segfault 和 RAM 限制(我只有 8GB RAM)。

例如,给定

data.frame(beg=c("a","a","b","b","c","c"),
           end=c("1","2","1","2","1","2"),
           weight=1:6)

我想要数据框

data.frame(beg=c("a","a","b"),
           end=c("b","c","c"),
           weight=c(1+3+2+4,1+5+2+6,3+5+4+6))

边的权重相加。

(在本例中,abc 是“较小”集,12 是“较大”集)。

【问题讨论】:

  • 我写了一个答案,然后我想我可能不明白你的意思。 “不构建二分图”是指您要避免构建其邻接矩阵?您是否假设该图是稀疏的?
  • @amit:我的担忧纯粹是务实的:我想避免内存不足和在igraph 中崩溃(请参阅编辑)。
  • 每种模式有多少个节点,二分图的预期密度是多少?如果使用稀疏矩阵不能解决问题(据我所知,这就是 igraph 使用的方法),那么在 R 中执行此操作可能会遇到一些麻烦。
  • @ndoogan:igraph 的问题是段错误
  • @ndoogan:用户(3,234,178)x 发布者(100)4,775,955 条边(密度 1.476714 %)的二分图

标签: r igraph bipartite


【解决方案1】:

这似乎可以满足我的需求(关键是使用data.table 进行快速加入):

> library(igraph)
> library(data.table)
data.table 1.8.8  For help type: help("data.table")
> f <- data.frame(beg=c("a","a","b","b","c","c"),
                  end=c("1","2","1","2","1","2"),
                  count=1:6)
> f
   beg end count
1:   a   1     1
2:   b   1     3
3:   c   1     5
4:   a   2     2
5:   b   2     4
6:   c   2     6
> m <- f[f,allow.cartesian=TRUE]

> m
    end beg weight beg.1 weight.1
 1:   1   a      1     a        1
 2:   1   b      3     a        1
 3:   1   c      5     a        1
 4:   1   a      1     b        3
 5:   1   b      3     b        3
 6:   1   c      5     b        3
 7:   1   a      1     c        5
 8:   1   b      3     c        5
 9:   1   c      5     c        5
10:   2   a      2     a        2
11:   2   b      4     a        2
12:   2   c      6     a        2
13:   2   a      2     b        4
14:   2   b      4     b        4
15:   2   c      6     b        4
16:   2   a      2     c        6
17:   2   b      4     c        6
18:   2   c      6     c        6
> v <- m$beg == m$beg.1
> m <- f[f,allow.cartesian=TRUE]
> v <- m$beg == m$beg.1
> m$end <- NULL
> m$weight <- (m$count + m$count.1)/2
> m$count <- NULL
> m$count.1 <- NULL
> m
    beg beg.1 weight
 1:   a     a      1
 2:   b     a      2
 3:   c     a      3
 4:   a     b      2
 5:   b     b      3
 6:   c     b      4
 7:   a     c      3
 8:   b     c      4
 9:   c     c      5
10:   a     a      2
11:   b     a      3
12:   c     a      4
13:   a     b      3
14:   b     b      4
15:   c     b      5
16:   a     c      4
17:   b     c      5
18:   c     c      6
> ve <- data.table(vertex=m$beg[v], weight=m$weight[v], key="vertex")
> ve <- ve[, list(count = .N, weight = sum(weight)), by = "vertex"]
> ve
   vertex count weight
1:      a     2      3
2:      b     2      7
3:      c     2     11
> g1 <- graph.data.frame(m[!v,], vertices=ve, directed=FALSE)
> g1 <- simplify(g1, edge.attr.comb="sum")
> V(g1)$weight
[1]  3  7 11
> E(g1)$weight
[1] 10 14 18

【讨论】:

    【解决方案2】:

    这就是我的做法(假设你的边在 df 中,而“小”集在边的开头)

    对于小集合中的每一对节点,我将使用以下内容:

    do.pair = function(x,y) {
         tmp = intersect(df$end[df$beg==x],df$end[df$beg==y])
         res = sum(df$weight[(df$beg %in% c(x,y)) & (df$end %in% tmp)])
         return(res)
    }
    

    现在,我会以你喜欢的方式创建对的列表(你可以使用 exapnd.grid 或 external),然后使用上面的相关 apply 函数,这里我只是做一个简单的嵌套循环,效率不是很高但易于阅读。

    g.small = unique(df$beg)
    n = length(g.small)
    res = list()
    cnt=0
    for (i in 1:(n-1)) {
        for (j in (i+1):n) {
           cnt = cnt+1
           res[[cnt]] = list(beg=g.small[i],end=g.small[j],weight=do.pair(g.small[i],g.small[j]))
        }
    }
    
    do.call(rbind,res)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-21
      • 2020-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 2021-06-18
      相关资源
      最近更新 更多