2016-04-13 24 views

cevap

3

olarak bu soruya Açıklamalarda belirttiği, ne GraphFrames ne de GRAPHX yerleşik ikili grafikler için destek. Bununla birlikte, her ikisinin de bipartite grafikleri oluşturmanıza izin verecek kadar fazla esnekliği vardır. Bir GraphX ​​çözümü için, bkz. this previous answer. Bu çözüm, farklı köşe/nesne tipi arasında paylaşılan bir özellik kullanır. Ve bu RDDs ile çalışırken, DataFrames için çalışmayacak. DataFrame numaralı satırdaki bir satırda sabit bir şema vardır - bazen price sütun içeremez ve bazen kullanılamaz. Bazen null olan bir price sütununa sahip olabilir, ancak sütunun her satırda bulunması gerekir.

Bunun yerine, GraphFrames için çözüm aslında senin ikili grafikte nesnelerin her iki tür doğrusal alt tipi olan bir DataFrame tanımlamak gerektiğini gibi görünüyor - bu her iki tip tüm alanları içermelidir nesneler. Bu aslında oldukça kolay - full_outer size bunu verecek. Böyle bir şey:

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") 

Daha sonra yaratabilecek bir süper-set böyle DataFrame:

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| 
+---+-------+----+------+------+ 

Sen structs ile bunu biraz daha temiz yapmak belki olabilir:

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| 
+---+------------+------------+ 

Ben Ayrıca, aynı çözümün, RDDs ile GraphX'da daha fazla veya daha az çalışacağına işaret eder. Her zaman herhangi traits paylaşmayan iki case classes katılmadan yoluyla köşe oluşturabilirsiniz: - Bir paylaşmak zorunda kalmadan önceki cevaba Saygılarımla

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)))) 

, bunu işlemek için daha esnek bir yol gibi görünüyor Kombine nesneler arasında trait.