如何使用子图函数来获取仅包含特定连接组件的顶点和边的图形?假设我知道连接组件ID,最终目标是基于连接组件创建新图。我想保留原始图表中的顶点属性。
答案 0 :(得分: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
}
}
答案 1 :(得分:2)
我提出你的问题,给定源图中的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.Either
更改为EdgeDirection.In
或EdgeDirection.Out
。
最后的.subgraph
会删除属性设置为null
的所有顶点。如果原始val graph
的顶点属性设置为null
,则无效。否则这是有效的,而无需事先知道Vertex属性类型。