2016-04-22 22 views
9

Ci sono due DataFrames (Scala, Apache Spark 1.6.1)Come unire due DataFrames in Scala e Apache Spark?

1) Corrisponde

  MatchID | Player1 | Player2 
     -------------------------------- 
       1 | John Wayne | John Doe 
       2 | Ive Fish | San Simon 

2) Dati Personali

   Player  | BirthYear 
       -------------------------------- 
       John Wayne | 1986 
       Ive Fish | 1990 
       San Simon | 1974 
       john Doe | 1995 

Come potrebbe creare un nuovo dataframe con 'Anno di nascita' per entrambi i giocatori

  MatchID | Player1 | Player2 | BYear_P1 |BYear_P2 | Diff 
     ------------------------------------------------------------- 
       1 | John Wayne | John Doe | 1986 | 1995 | 9 
       2 | Ive Fish | San Simon | 1990 | 1974 | 16 

?

ho cercato

val df = MatchesDF.join(PersonalDF, MatchesDF("Player1") === PersonalDF("Player")) 

poi unirsi di nuovo per il secondo giocatore

val resDf = df.join(PersonalDF, df("Player2") === PersonalDF("Player")) 

ma è in termini di tempo di funzionamento molto.

Potrebbe essere un altro modo per farlo in Scala e Apache Spark?

risposta

7

Questo dovrebbe funzionare meglio:

case class Match(matchId: Int, player1: String, player2: String) 
case class Player(name: String, birthYear: Int) 

val matches = Seq(
    Match(1, "John Wayne", "John Doe"), 
    Match(2, "Ive Fish", "San Simon") 
) 

val players = Seq(
    Player("John Wayne", 1986), 
    Player("Ive Fish", 1990), 
    Player("San Simon", 1974), 
    Player("John Doe", 1995) 
) 

val matchesDf = sqlContext.createDataFrame(matches) 
val playersDf = sqlContext.createDataFrame(players) 

matchesDf.registerTempTable("matches") 
playersDf.registerTempTable("players") 

sqlContext.sql(
    "select matchId, player1, player2, p1.birthYear, p2.birthYear, abs(p1.birthYear-p2.birthYear) " + 
    "from matches m inner join players p1 inner join players p2 " + 
    "where m.player1 = p1.name and m.player2 = p2.name").show() 

+-------+----------+---------+---------+---------+---+ 
|matchId| player1| player2|birthYear|birthYear|_c5| 
+-------+----------+---------+---------+---------+---+ 
|  1|John Wayne| John Doe|  1986|  1995| 9| 
|  2| Ive Fish|San Simon|  1990|  1974| 16| 
+-------+----------+---------+---------+---------+---+ 

non ho trovato il modo di esprimere unirsi di 3 tavoli in Scala DSL.

+0

di nuovo facendo due si unisce, come ci si renderla migliore? – void

+0

Esegui circa 2 minuti per la tabella delle corrispondenze con ~ 10000 righe e Tabella giocatori con ~ 700 record – gmlvsv

+1

utilizza i frame di dati per i tuoi join anziché SQL semplice per prestazioni migliori. – dheee

4
val df = left.join(right, Seq("name")) 
display(df) 
+6

Ciao e benvenuto su StackOverflow. Aggiungi alcune spiegazioni alla tua risposta in modo che diventi più utile per gli altri utenti. Vedi http://stackoverflow.com/help/how-to-answer – wmk

+0

Queste informazioni non sono sufficienti per fornire alcun tipo di aiuto. Cos'è rimasto"? Cos'è giusto"? Si prega di riformulare la risposta .. –

+0

Non c'è alcuna funzione come visualizzazione in Spark Dataframe (implementazione Scala) –

6

Si tratta di una soluzione che utilizza funzioni dataframe di scintilla:

import sqlContext.implicits._ 
import org.apache.spark.sql.Row 
import org.apache.spark.sql.functions.abs 

val matches = sqlContext.sparkContext.parallelize(Row(1, "John Wayne", "John Doe"), Row(2, "Ive Fish", "San Simon"))) 

val players = sqlContext.sparkContext.parallelize(Seq(
    Row("John Wayne", 1986), 
    Row("Ive Fish", 1990), 
    Row("San Simon", 1974), 
    Row("John Doe", 1995) 
)) 

val matchesDf = sqlContext.createDataFrame(matches, StructType(Seq(
    StructField("matchId", IntegerType, nullable = false), 
    StructField("player1", StringType, nullable = false), 
    StructField("player2", StringType, nullable = false))) 
).as('matches) 

val playersDf = sqlContext.createDataFrame(players, StructType(Seq(
    StructField("player", StringType, nullable = false), 
    StructField("birthYear", IntegerType, nullable = false) 
))).as('players) 

matchesDf 
    .join(playersDf, $"matches.player1" === $"players.player") 
    .select($"matches.matchId" as "matchId", $"matches.player1" as "player1", $"matches.player2" as "player2", $"players.birthYear" as "player1BirthYear") 
    .join(playersDf, $"player2" === $"players.player") 
    .select($"matchId" as "MatchID", $"player1" as "Player1", $"player2" as "Player2", $"player1BirthYear" as "BYear_P1", $"players.birthYear" as "BYear_P2") 
    .withColumn("Diff", abs('BYear_P2.minus('BYear_P1))) 
    .show() 

+-------+----------+---------+--------+--------+----+ 
|MatchID| Player1| Player2|BYear_P1|BYear_P2|Diff| 
+-------+----------+---------+--------+--------+----+ 
|  1|John Wayne| John Doe| 1986| 1995| 9| 
|  2| Ive Fish|San Simon| 1990| 1974| 16| 
+-------+----------+---------+--------+--------+----+