【问题标题】:Efficient way of calculating average value of connections in igraph?计算igraph中连接平均值的有效方法?
【发布时间】:2014-04-03 10:31:40
【问题描述】:

我正在使用 igraph R 中的一个相当大的图。(约 500 万个顶点,4000 万条边)。

我想为每个顶点创建一个新属性,它是它们每个连接的属性的平均值。

例如:

人 A 的 X 值为 10,他们与人 B、C 和 D 相关联,他们的 x 值分别为 20、50 和 65。我想为人 A 分配一个新值 45(平均值为 20、50 和 65)。

我目前正在使用以下方法(来自另一个 stackoverflow 答案)(我使用的是 10 个核心)

adjcency_list <- get.adjlist(g)

avg_contact_val <- ldply(adjcency_list, function(neis){ mean(V(g)[neis]$X, na.rm = T)}, 
                      .parallel = TRUE
                      )

V(g)$avg_contact_val  <- avg_contact_val 

这完全符合我的需要,但它不能很好地扩展,并且需要(非常!)很长时间才能在完整的图表上完成。

  • 有没有更有效的方法来做到这一点?
  • 这是否属于使用 x 值而不是度数的页面排名类型算法
  • 能否以某种方式使用 GPU?
  • 这在 igraph Python 中会更快吗?

编辑:

以下是一些示例数据和对建议方法的尝试:

set.seed(12345)
g <- erdos.renyi.game(10000, .0005)
V(g)$NAME <- c(1:10000)
V(g)$X <- round(runif(10000,0,30))

adjcency_list <- get.adjlist(g)

sub_ages <- data.frame(NAME = V(g)$NAME, X = V(g)$X)
dta.table <- data.table(sub_ages, key = "NAME")

数据表方法

system.time(
avg_contact_ages <- ldply(adjcency_list, 
                          function(neis){ 
                                  mean(dta.table[neis,mean(X)], na.rm = T)
                                  }, .progress = "tk"
                          )
)

user  system elapsed 
38.87    1.50   40.37 

数据框架方法

sub_ages2 <- data.frame(row.names = V(g)$NAME, X = V(g)$X)

system.time(
avg_contact_ages <- ldply(adjcency_list, 
                        function(neis){ 
                          mean(sub_ages2[neis, "X"], na.rm = T)
                        }, .progress = "tk"
  )
)

user  system elapsed 
8.69    1.28    9.99 

原始方法

system.time(
avg_contact_ages <- ldply(adjcency_list, 
                          function(neis){ 
                            mean(V(g)[neis]$X, na.rm = T)
                          } , .progress = "tk"
                      )
)

user  system elapsed 
16.74    2.35   19.14 

影子的方法

system.time(
  avg_nei <- ldply(V(g), function(vert){
    mean(get.vertex.attribute(g, "X", index=neighbors(g,vert)), na.rm=TRUE)
  }, .progress = "tk")
)

user  system elapsed 
8.80    1.42   10.23 

【问题讨论】:

    标签: r parallel-processing plyr igraph


    【解决方案1】:
    • 有没有更有效的方法来做到这一点?

    我想是的。不要一直调用V(g),而是将属性放在一个向量中,并对其进行索引。如果您包含一些示例数据,那么我还将包含一些代码。

    • 这是否属于使用 x 值而不是度数的页面排名类型算法

    不,PageRank 是递归的,你的排名取决于整个网络,而不仅仅是你邻居的分数。

    • 能否以某种方式使用 GPU?

    不适用于 igraph。如果没有 GPU,你当然可以让这个速度足够快,所以我不会那样做。

    • 这在 igraph Python 中会更快吗?

    看你怎么写。如果您在 R 中以正确的方式编写它,那么它在 Python 中也不会更快,imo。

    编辑:

    我省略了进度条,因为它实际上是最慢的。

    上面使用数据框的最快解决方案

    system.time({
      sub_ages2 <- data.frame(row.names = V(g)$NAME, X = V(g)$X);
      avg_contact_ages <- ldply(adjcency_list, function(neis) {
        mean(sub_ages2[neis, "X"], na.rm = T)
      })
    })
    #    user  system elapsed 
    #   0.368   0.020   0.386 
    

    sapply 稍微快一点

    system.time({
      sub_ages2 <- data.frame(row.names = V(g)$NAME, X = V(g)$X);
      avg_contact_ages <- sapply(adjcency_list, function(neis) {
        mean(sub_ages2[neis, "X"], na.rm = TRUE)
      })
    })
    #    user  system elapsed 
    #   0.340   0.017   0.356 
    

    使用因素

    system.time({
      adj_vec <- unlist(adjcency_list)
      adj_fac <- factor(rep(seq_along(adjcency_list),
                     sapply(adjcency_list, length)),levels=seq_len(vcount(g)))
      avg_contact_ages <- tapply(V(g)$X[adj_vec], adj_fac, mean, na.rm=TRUE)
    })
    #    user  system elapsed 
    #   0.131   0.008   0.138 
    

    如果您需要更高的加速,您可能需要使用 C/C++,Rcpp 将是一个相对简单的解决方案。

    【讨论】:

    • 我添加了一些样本数据和一些测试。 data.frame 方法是您建议的吗?您能提供任何改进吗?
    • @Ger:谢谢,今天晚些时候再看,现在需要运行。顺便提一句。请在您的示例代码中设置随机种子,以实现可重复性。谢谢
    【解决方案2】:

    函数get.vertex.attribute 增加了一些速度。但是对于您的图表的大小,这可能还不够。无论如何,这是我稍微快一点的版本(在我对小得多的图表的基准测试中,它比你的版本快了大约 2.5 倍):

    avg_nei <- ldply(V(g), function(vert){
      mean(get.vertex.attribute(g, "X", index=neighbors(g,vert)), na.rm=TRUE)
    }, .parallel = TRUE)
    V(g)$avg_contact_val <- avg_nei
    

    【讨论】:

    • 感谢影子,当然更快...见上面的速度测试
    猜你喜欢
    • 1970-01-01
    • 2017-10-12
    • 2012-07-01
    • 2013-11-27
    • 1970-01-01
    • 2017-09-10
    • 2012-07-06
    • 1970-01-01
    • 2015-05-03
    相关资源
    最近更新 更多