2016-04-22 12 views
9

Istnieją dwa DataFrames (Scala, Apache Spark 1.6.1)Jak dołączyć do dwóch DataFrames w Scala i Apache Spark?

1) pasuje

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

2) Dane osobowe

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

Jak można utworzyć nowy DataFrame z 'BirthYear' dla obu graczy:

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

?

Próbowałem

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

następnie przystąpić ponownie do drugiego gracza

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

ale to bardzo czasochłonna operacja.

Może być inny sposób, aby to zrobić w Scala i Apache Spark?

Odpowiedz

7

Należy to wykonać lepiej:

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

nie mogę znaleźć sposobu wyrażania przyłączenia z 3 tabel w Scala DSL.

+0

znowu robi dwa przyłącza, jak to zrobić to lepiej? – void

+0

Ten przebieg około 2 minut dla tabeli Dopasowania z ~ 10000 rzędami i Tabela graczy z ~ 700 rekordów – gmlvsv

+1

używa ramek danych dla twoich połączeń zamiast zwykłego sql dla lepszej wydajności. – dheee

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

Witam i zapraszam do StackOverflow. Proszę dodać wyjaśnienie do odpowiedzi, aby stała się bardziej wartościowa dla innych użytkowników. Zobacz http://stackoverflow.com/help/how-to-answer – wmk

+0

Ta informacja nie jest wystarczająca, aby zapewnić jakąkolwiek pomoc. Co zostało"? Co jest słuszne"? Proszę przeformułować odpowiedź .. –

+0

Nie ma takiej funkcji jak wyświetlanie w Spark Dataframe (implementacja Scala) –

6

Jest to rozwiązanie wykorzystujące funkcje dataframe Sparka:

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| 
+-------+----------+---------+--------+--------+----+ 
Powiązane problemy