Wie Subgraph-Funktion verwenden, um ein Diagramm zu erhalten, das nur Scheitelpunkte und Kanten von der bestimmten verbundenen Komponente enthalten würde? Nehmen wir an, ich kenne die ID der verbundenen Komponente, das Endziel ist die Erstellung eines neuen Graphen basierend auf der verbundenen Komponente. Ich möchte die Scheitelpunktattribute vom ursprünglichen Diagramm beibehalten.Apache Spark GraphX verbundene Komponenten
Antwort
Sie müssen das Diagramm mit den Komponenten-IDs an das ursprüngliche Diagramm anfügen, filtern (den Untergraphen verwenden) anhand der Komponenten-ID und verwerfen dann die Komponenten-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
}
}
Ich nehme Ihre Frage zu sein, ein VertexId in einem Quelldiagramm gegeben, ein neues Diagramm mit den Knoten erstellen und Kanten zu diesem VertexId aus dem Quelldiagramm verbunden.
Da, hier ist was ich tun würde:
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})
paar Dinge zu beachten:
Sie EdgeDirection.Either
-EdgeDirection.In
oder EdgeDirection.Out
nach Bedarf ändern können.
Die .subgraph
am Ende entfernt alle Scheitelpunkte, für die das Attribut auf null
festgelegt ist. Wenn das Original val graph
Scheitelpunkte mit Attributen hat, die auf null
festgelegt sind, wird dies nicht funktionieren. Ansonsten funktioniert das, ohne den Vertex-Attributtyp im Voraus kennen zu müssen.
Danke für diese Funktion! Aber können wir nicht davon ausgehen, dass, wenn Sie die CC-ID haben, Sie wahrscheinlich bereits das CC konstruiert haben, so dass dieses als eines der 'getComponent'-Argumente eingezogen werden kann, was die potentiell teure Aufgabe der Neuberechnung speichert. Ich bin neugierig, warum diese Funktion funktioniert, aber wenn ich die Schritte manuell manuell ein "Long" oder was auch immer in als die "Komponente" setzen, schlägt es fehl. Muss es "Some" oder "VertexId" sein? – SpmP
Sie haben recht - jetzt, wo ich es anschaue, ist es ziemlich seltsam, wie wir eine Komponenten-ID haben würden, bevor wir 'ConnectedComponents' ausführen. Ich glaube, ich wollte nur 'ConnectedComponents' irgendwo hin mitnehmen. Ich werde den Code überarbeiten, um vernünftiger zu sein. Für Ihre andere Frage: 'VertexId' ist ein Alias für' Long'. Eine einfache alte Nummer sollte dort funktionieren. Was meinst du mit "scheitert" hier? Hast du eine Ausnahme? –
Wissen Sie, wie man die Anzahl der verbundenen Komponenten in einem Graphen zählt? – ELI