Scala如何匹配两个dfs,如果匹配,则在第一个df中更新密钥并从所需的df中选择所有列

时间:2018-03-05 05:38:59

标签: scala apache-spark

我有两个数据框中的数据:

selectedPersonDF:

ID    key  Name
1          lak
2          Mouny   
3          kkk
4          nnn
5          hhh

selectedDetailsDF:

first  second third  key
--------------------------
1       9       9    777
9       8       8    878
8       10      10   765
10      12      19   909
11      2       20   708

val columnsToCheck = selectedDetailsDF.columns.toSet - "key" toList

import org.apache.spark.sql.functions._
val tempSelectedDetailsDF = selectedDetailsDF.select(array(columnsToCheck.map(col): _*).as("array"), col("key").as("key2"))



val arrayContains = udf((array: collection.mutable.WrappedArray[String], value: String) => array.contains(value))

val finalDF = selectedPersonDF.join(tempSelectedDetailsDF, arrayContains($"array", $"ID"), "left")
  .select($"ID", $"key2".as("key"))
  .na.fill("")

获得如下输出,

+---+---+
|ID |key|
+---+---+
|1  |777|
|2  |708|
|3  |   |
|4  |   |
|5  |   |
+---+---+

期待: 我想显示来自selectedPersonDF的所有列我必须将selectedPersonDF id列与selectedDetailsDF匹配所有列(First,Second,Third)如果任何列数据与person id匹配则我们必须从selectedDetailsDF获取键值必须在selectedPersonDF键列中更新

ID    key  Name
1     777  lak
2     708  Mouny   
3          kkk
4          nnn
5          hhh

请帮助我。

2 个答案:

答案 0 :(得分:2)

只需选择Name

val finalDF = selectedPersonDF.join(tempSelectedDetailsDF, arrayContains($"array", $"ID"), "left")
  .select($"ID", $"key", $"Name")
  .na.fill("")

你应该没问题

如果selectedPersonDF中有更多列,并且您希望select所有列都为

val columnsToSelect = selectedPersonDF.columns
val finalDF = selectedPersonDF.join(tempSelectedDetailsDF, arrayContains($"array", $"ID"), "left")
  .select(columnToSelect.map(col): _*)
  .na.fill("")

答案 1 :(得分:0)

我建议您使用有助于优化的内置函数,而不是使用UDF

您可以使用多个键的组合来加入并获得结果,如下所示

  val joinCondition = df1("ID") === selectedDetailsDF("A") ||
    df1("ID") === selectedDetailsDF("B") ||
    df1("ID") === selectedDetailsDF("C")

  val df2 = df1.drop("key")
    .join(selectedDetailsDF, joinCondition, "left")
    .drop("A", "B", "c")
    .withColumnRenamed("D", "key")
    .na.fill("")

我希望这更优化而不是使用udf。我希望这会对你有所帮助。