2015-08-28 72 views
1

這個問題是前一個問題的「續集」。我新來激發graphx和scala,我想知道如何執行下面的操作。圖形之間的結構操作符

我該如何合併兩個圖形進入一個新的圖形,使新的圖形具有以下屬性:

兩個圖形的共同邊緣的屬性平均(或更一般的方式,應用邊緣屬性之間的平均函數(邊緣屬性是類型雙))

我們認爲共同的邊緣=相同srcId和相同dstId,並且頂點和邊是唯一的。

回答

2

假設你只有兩個圖,並都含有相同的一組頂點,而不可以用結合邊緣和新的圖形使用groupEdges方法重複邊緣:

val graph1: Graph[T,Double] = ??? 
val graph2: Graph[T,Double] = ??? 

Graph(graph1.vertices, graph1.edges.union(graph2.edges)) 
    .groupEdges((val1, val2) => (val1 + val2)/2.0) 

或者多一點點通用:

Graph(graph1.vertices, graph1.edges.union(graph2.edges)) 
    .mapEdges(e => (e.attr, 1.0)) 
    .groupEdges((val1, val2) => (val1._1 + val2._1, val1._2 + val2._2)) 
    .mapEdges(e => e.attr._1/e.attr._2) 

如果這還不夠,你可以結合價值觀和從頭開始創建一個新的圖:

def edgeToPair (e: Edge[Double]) = ((e.srcId, e.dstId), e.attr) 
val pairs1 = graph1.edges.map(edgeToPair) 
val pairs2 = graph2.edges.map(edgeToPair) 

// Combine edges 
val newEdges = pairs1.union(pairs2) 
    .aggregateByKey((0.0, 0.0))(
    (acc, e) => (acc._1 + e, acc._2 + 1.0), 
    (acc1, acc2) => (acc1._1 + acc2._1, acc1._2 + acc2._2) 
).map{case ((srcId, dstId), (acc, count)) => Edge(srcId, dstId, acc/count)} 

// Combine vertices assuming there are no conflicts 
// like different labels 
val newVertices = graph1.vertices.union(graph2.vertices).distinct 

// Create new graph 
val newGraph = Graph(newVertices, newEdges) 

其中aggregateByKey可以替換爲groupByKey,然後映射,需要所有的值一次,如中位數。

+0

因爲我很喜歡這個答案。考慮性能問題而不考慮'combineByKey'更合適。你怎麼看? – eliasah

+0

而不是'aggregateByKey'? – zero323

+0

不是'groupByKey' – eliasah