J'ai construit deux dataframes. Comment pouvons-nous joindre plusieurs Spark dataframes?
Par exemple :
PersonDf
, ProfileDf
avec une colonne commune comme personId
as (clé). Maintenant, comment pouvons-nous avoir un Dataframe combinant PersonDf
et ProfileDf
?
Vous pouvez utiliser la classe de cas pour préparer un échantillon de données ... qui est facultatif par exemple: vous pouvez aussi obtenir DataFrame
à partir de hiveContext.sql
..
import org.Apache.spark.sql.functions.col
case class Person(name: String, age: Int, personid : Int)
case class Profile(name: String, personid : Int , profileDescription: String)
val df1 = sqlContext.createDataFrame(
Person("Bindu",20, 2)
:: Person("Raphel",25, 5)
:: Person("Ram",40, 9):: Nil)
val df2 = sqlContext.createDataFrame(
Profile("Spark",2, "SparkSQLMaster")
:: Profile("Spark",5, "SparkGuru")
:: Profile("Spark",9, "DevHunter"):: Nil
)
// you can do alias to refer column name with aliases to increase readablity
val df_asPerson = df1.as("dfperson")
val df_asProfile = df2.as("dfprofile")
val joined_df = df_asPerson.join(
df_asProfile
, col("dfperson.personid") === col("dfprofile.personid")
, "inner")
joined_df.select(
col("dfperson.name")
, col("dfperson.age")
, col("dfprofile.name")
, col("dfprofile.profileDescription"))
.show
exemple d'approche de table temporaire que je n'aime pas personnellement ...
df_asPerson.registerTempTable("dfperson");
df_asProfile.registerTempTable("dfprofile")
sqlContext.sql("""SELECT dfperson.name, dfperson.age, dfprofile.profileDescription
FROM dfperson JOIN dfprofile
ON dfperson.personid == dfprofile.personid""")
Remarque: 1) Comme mentionné par @ RaphaelRoth ,
val resultDf = PersonDf.join(ProfileDf,Seq("personId"))
est une bonne approche car il ne contient pas de colonnes dupliquées des deux côtés si vous utilisez une jointure interne avec la même table.
2) Exemple Spark 2.x mis à jour dans une autre réponse avec l'ensemble complet des opérations de jointure supportées par spark 2.x avec exemples + résultat
En outre, une chose importante dans les jointures: fonction de diffusion peut aider à donner un indice s'il vous plaît voir ma réponse
vous pouvez utiliser
val resultDf = PersonDf.join(ProfileDf, PersonDf("personId") === ProfileDf("personId"))
ou plus court et plus flexible (comme vous pouvez facilement spécifier plus de 1 colonnes pour rejoindre)
val resultDf = PersonDf.join(ProfileDf,Seq("personId"))
Une manière
// join type can be inner, left, right, fullouter
val mergedDf = df1.join(df2, Seq("keyCol"), "inner")
// keyCol can be multiple column names seperated by comma
val mergedDf = df1.join(df2, Seq("keyCol1", "keyCol2"), "left")
Autrement
import spark.implicits._
val mergedDf = df1.as("d1").join(df2.as("d2"), ($"d1.colName" === $"d2.colName"))
// to select specific columns as output
val mergedDf = df1.as("d1").join(df2.as("d2"), ($"d1.colName" === $"d2.colName")).select($"d1.*", $"d2.anotherColName")
De https://spark.Apache.org/docs/1.5.1/api/Java/org/Apache/spark/sql/DataFrame.html , utilisez join
:
Équi-jointure interne avec un autre DataFrame en utilisant la colonne donnée.
PersonDf.join(ProfileDf,$"personId")
OR
PersonDf.join(ProfileDf,PersonDf("personId") === ProfileDf("personId"))
Mise à jour:
Vous pouvez également enregistrer la DFs
en tant que table temporaire à l'aide de df.registerTempTable("tableName")
et vous pouvez écrire des requêtes SQL à l'aide de sqlContext
.