title: Efficient way of calculating average value of connections in igraph?
body: <p>I'm working with a fairly large graph in igraph R. (~5 million vertices, 40 million edges).</p>
  
  <p>I want to create a new attribute for each vertex which is the average value of an attribute of each of their connections. </p>
  
  <p>For example:</p>
  
  <p>Person A has an X value of 10, they're connected to persons B, C and D who have x values of 20, 50 and 65 respectively. I want to assign a new value of 45 to Person A (average of 20, 50 and 65).</p>
  
  <p>I'm currently using the following method (from another stackoverflow answer) (I'm using 10 cores)</p>
  
  <pre><code>adjcency_list &lt;- get.adjlist(g)
  
  avg_contact_val &lt;- ldply(adjcency_list, function(neis){ mean(V(g)[neis]$X, na.rm = T)}, 
                        .parallel = TRUE
                        )
  
  V(g)$avg_contact_val  &lt;- avg_contact_val 
  </code></pre>
  
  <p>This works exactly as I need it to, but it doesn't scale very well and would take a (very!) long time to do on the full graph.</p>
  
  <ul>
  <li>Is there a more efficient method of doing this? </li>
  <li>Could this fall under a page rank type algorithm using the x value instead of degree</li>
  <li>Would it be possible to use a GPU somehow?</li>
  <li>Would this be quicker in igraph Python?</li>
  </ul>
  
  <h1>EDIT:</h1>
  
  <p>Here's some sample data and an attempt at the approaches suggested:</p>
  
  <pre><code>set.seed(12345)
  g &lt;- erdos.renyi.game(10000, .0005)
  V(g)$NAME &lt;- c(1:10000)
  V(g)$X &lt;- round(runif(10000,0,30))
  
  adjcency_list &lt;- get.adjlist(g)
  
  sub_ages &lt;- data.frame(NAME = V(g)$NAME, X = V(g)$X)
  dta.table &lt;- data.table(sub_ages, key = "NAME")
  </code></pre>
  
  <h1>DATA TABLE APPROACH</h1>
  
  <pre><code>system.time(
  avg_contact_ages &lt;- 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 
  </code></pre>
  
  <h1>DATA FRAME APPROACH</h1>
  
  <pre><code>sub_ages2 &lt;- data.frame(row.names = V(g)$NAME, X = V(g)$X)
  
  system.time(
  avg_contact_ages &lt;- ldply(adjcency_list, 
                          function(neis){ 
                            mean(sub_ages2[neis, "X"], na.rm = T)
                          }, .progress = "tk"
    )
  )
  
  user  system elapsed 
  8.69    1.28    9.99 
  </code></pre>
  
  <h1>ORIGINAL APPROACH</h1>
  
  <pre><code>system.time(
  avg_contact_ages &lt;- ldply(adjcency_list, 
                            function(neis){ 
                              mean(V(g)[neis]$X, na.rm = T)
                            } , .progress = "tk"
                        )
  )
  
  user  system elapsed 
  16.74    2.35   19.14 
  </code></pre>
  
  <h1>Shadow's approach</h1>
  
  <pre><code>system.time(
    avg_nei &lt;- 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 
  </code></pre>