Unterstützt GraphFrames api die Erstellung von Bipartite-Grafiken in der aktuellen Version?Unterstützt GraphFrames api die Erstellung von Bipartite-Graphen?
Aktuelle Version: 0.1.0
Spark-Version: 1.6.1
Unterstützt GraphFrames api die Erstellung von Bipartite-Grafiken in der aktuellen Version?Unterstützt GraphFrames api die Erstellung von Bipartite-Graphen?
Aktuelle Version: 0.1.0
Spark-Version: 1.6.1
Wie in den Kommentaren zu dieser Frage wies darauf hin, weder GraphFrames noch GraphX haben eingebaute Unterstützung für bipartite Graphen. Beide haben jedoch mehr als genug Flexibilität, um zweiseitige Graphen erstellen zu können. Eine GraphX-Lösung finden Sie unter this previous answer. Diese Lösung verwendet ein gemeinsames Merkmal zwischen dem unterschiedlichen Vertex-/Objekttyp. Und während das mit RDDs
funktioniert, wird das für DataFrames
nicht funktionieren. Eine Zeile in einem DataFrame
hat ein festes Schema - es kann manchmal keine price
Spalte enthalten und manchmal nicht. Es kann eine price
Spalte haben, die manchmal null
ist, aber die Spalte muss in jeder Zeile existieren.
Stattdessen scheint die Lösung für GraphFrames
zu sein, dass Sie ein DataFrame
definieren müssen, die im Wesentlichen eine lineare Untertyp der beiden Arten von Objekten in der zweiteiligen Graphen ist - es hat alle Felder beiden Typen enthält von Objekte. Das ist eigentlich ziemlich einfach - ein join
mit full_outer
wird Ihnen das geben. Etwas wie folgt aus:
val players = Seq(
(1,"dave", 34),
(2,"griffin", 44)
).toDF("id", "name", "age")
val teams = Seq(
(101,"lions","7-1"),
(102,"tigers","5-3"),
(103,"bears","0-9")
).toDF("id","team","record")
Sie könnten dann erstellen ein Super-Set DataFrame
wie folgt aus:
val teamPlayer = players.withColumnRenamed("id", "l_id").join(
teams.withColumnRenamed("id", "r_id"),
$"r_id" === $"l_id", "full_outer"
).withColumn("l_id", coalesce($"l_id", $"r_id"))
.drop($"r_id")
.withColumnRenamed("l_id", "id")
teamPlayer.show
+---+-------+----+------+------+
| id| name| age| team|record|
+---+-------+----+------+------+
|101| null|null| lions| 7-1|
|102| null|null|tigers| 5-3|
|103| null|null| bears| 0-9|
| 1| dave| 34| null| null|
| 2|griffin| 44| null| null|
+---+-------+----+------+------+
Man könnte es vielleicht ein wenig zu Reiniger mit structs
:
val tpStructs = players.select($"id" as "l_id", struct($"name", $"age") as "player").join(
teams.select($"id" as "r_id", struct($"team",$"record") as "team"),
$"l_id" === $"r_id",
"full_outer"
).withColumn("l_id", coalesce($"l_id", $"r_id"))
.drop($"r_id")
.withColumnRenamed("l_id", "id")
tpStructs.show
+---+------------+------------+
| id| player| team|
+---+------------+------------+
|101| null| [lions,7-1]|
|102| null|[tigers,5-3]|
|103| null| [bears,0-9]|
| 1| [dave,34]| null|
| 2|[griffin,44]| null|
+---+------------+------------+
I‘ Ich werde auch darauf hinweisen, dass mehr oder weniger die gleiche Lösung in GraphX
mit RDDs
funktionieren würde. Man konnte immer eine Ecke erstellen über die Verbindung von zwei case classes
, die keine traits
teilen:
case class Player(name: String, age: Int)
val playerRdd = sc.parallelize(Seq(
(1L, Player("date", 34)),
(2L, Player("griffin", 44))
))
case class Team(team: String, record: String)
val teamRdd = sc.parallelize(Seq(
(101L, Team("lions", "7-1")),
(102L, Team("tigers", "5-3")),
(103L, Team("bears", "0-9"))
))
playerRdd.fullOuterJoin(teamRdd).collect foreach println
(101,(None,Some(Team(lions,7-1))))
(1,(Some(Player(date,34)),None))
(102,(None,Some(Team(tigers,5-3))))
(2,(Some(Player(griffin,44)),None))
(103,(None,Some(Team(bears,0-9))))
Bei allem Respekt auf die vorherige Antwort, scheint dies eine flexiblere Art und Weise zu handhaben - ohne mit teilen trait
zwischen den kombinierten Objekten.
Nein, dies gilt auch für GraphX, es sei denn, Sie folgen der bereitgestellten Lösung [hier] (http://stackoverflow.com/a/33243012/3415409) – eliasah