8

如何使用子图函数来获取仅包含来自特定连接组件的顶点和边的图?假设我知道连通组件 id,最终目标是基于连通组件创建一个新图。我想保留原始图中的顶点属性。

4

2 回答 2

6

您必须将具有组件 ID 的图加入原始图,按组件 ID 过滤(获取子图),然后丢弃组件 ID。

import scala.reflect._
import org.apache.spark.graphx._
import org.apache.spark.graphx.lib.ConnectedComponents

def getComponent[VD: ClassTag, ED: ClassTag](
    g: Graph[VD, ED], component: VertexId): Graph[VD, ED] = {
  val cc: Graph[VertexId, ED] = ConnectedComponents.run(g)
  // Join component ID to the original graph.
  val joined = g.outerJoinVertices(cc.vertices) {
    (vid, vd, cc) => (vd, cc)
  }
  // Filter by component ID.
  val filtered = joined.subgraph(vpred = {
    (vid, vdcc) => vdcc._2 == Some(component)
  })
  // Discard component IDs.
  filtered.mapVertices {
    (vid, vdcc) => vdcc._1
  }
}
于 2015-05-26T15:11:34.107 回答
3

我认为您的问题是,给定源图中的 VertexId,创建一个新图,其中节点和边从源图中连接到该 VertexId。

鉴于此,这就是我要做的:

val targetVertexId = ...
val graph = Graph(..., ...)
val newGraph = Graph(
  graph.vertices.filter{case (vid,attr) => vid == targetVertexId} ++
  graph.collectNeighbors(EdgeDirection.Either)
    .filter{ case (vid,arr) => vid == targetVertexId}
    .flatMap{ case (vid,arr) => arr},
  graph.edges
).subgraph(vpred = { case (vid,attr) => attr != null})

需要注意的几点:

您可以根据需要更改EdgeDirection.EitherEdgeDirection.In更改EdgeDirection.Out

最后.subgraph的 删除属性设置为 的所有顶点null。如果原件val graph具有属性设置为nullthis 的 Vertices 将不起作用。否则,这可以工作,而无需事先知道 Vertex 属性类型。

于 2015-05-27T03:18:11.593 回答