簡體   English   中英

在Scala Spark中連接不同的Dataframe時動態選擇多個列

[英]Dynamically select multiple columns while joining different Dataframe in Scala Spark

我有兩個火花數據幀df1df2 有沒有辦法在加入這兩個數據幀時動態選擇輸出列? 在內連接的情況下,以下定義輸出來自df1和df2的所有列。

def joinDF (df1: DataFrame,  df2: DataFrame , joinExprs: Column, joinType: String): DataFrame = {   
  val dfJoinResult = df1.join(df2, joinExprs, joinType)
  dfJoinResult
  //.select()
}

輸入數據:

val df1 = List(("1","new","current"), ("2","closed","saving"), ("3","blocked","credit")).toDF("id","type","account")
val df2 = List(("1","7"), ("2","5"), ("5","8")).toDF("id","value")

預期結果:

val dfJoinResult = df1
  .join(df2, df1("id") === df2("id"), "inner")
  .select(df1("type"), df1("account"), df2("value")) 

dfJoinResult.schema():

StructType(StructField(type,StringType,true), 
StructField(account,StringType,true), 
StructField(value,StringType,true))

我查看了df.select(cols.head, cols.tail: _*)等選項df.select(cols.head, cols.tail: _*)但它不允許從兩個DF中選擇列。 有沒有辦法動態傳遞selectExpr列以及我們想要從我的def選擇它的數據幀詳細信息? 我正在使用Spark 2.2.0。

可以將select表達式作為Seq[Column]傳遞給方法:

def joinDF(df1: DataFrame,  df2: DataFrame , joinExpr: Column, joinType: String, selectExpr: Seq[Column]): DataFrame = {   
  val dfJoinResult = df1.join(df2, joinExpr, joinType)
  dfJoinResult.select(selectExpr:_*)
}

要調用方法,請使用:

val joinExpr = df1.col("id") === df2.col("id")
val selectExpr = Seq(df1.col("type"), df1.col("account"), df2.col("value"))

val testDf = joinDF(df1, df2, joinExpr, "inner", selectExpr)

這將產生預期的結果:

+------+-------+-----+
|  type|account|value|
+------+-------+-----+
|   new|current|    7|
|closed| saving|    5|
+------+-------+-----+

在上面的selectExpr ,有必要指定列來自哪個數據幀。 但是, 如果滿足以下假設 ,則可以進一步簡化

  1. join的列在兩個數據框中具有相同的名稱
  2. 要選擇的列具有唯一名稱(另一個數據框沒有具有相同名稱的列)

在這種情況下,可以將joinExpr: Column更改為joinExpr: Seq[String]selectExpr: Seq[Column]以選擇selectExpr: Seq[String]

def joinDF(df1: DataFrame,  df2: DataFrame , joinExpr: Seq[String], joinType: String, selectExpr: Seq[String]): DataFrame = {   
  val dfJoinResult = df1.join(df2, joinExpr, joinType)
  dfJoinResult.select(selectExpr.head, selectExpr.tail:_*)
}

現在調用方法看起來更干凈:

val joinExpr = Seq("id")
val selectExpr = Seq("type", "account", "value")

val testDf = joinDF(df1, df2, joinExpr, "inner", selectExpr)

注意 :使用Seq[String]執行join ,與使用表達式相比,結果數據幀的列名稱將不同。 當存在具有相同名稱的列時,之后將無法單獨選擇這些列。

從上面給出的一個稍微修改過的解決方案是在執行連接之前,事先從DataFrames中選擇所需的列,因為它將具有較少的開銷,因為執行JOIN操作的列數較少。

val dfJoinResult = df1.select("column1","column2").join(df2.select("col1"),joinExpr,joinType)

但請記住選擇要執行連接操作的列,因為它將首先選擇列,然后從可用數據中選擇連接操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM