2015-08-28 70 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