如何在spark Dataframe上执行合并操作?

时间:2016-10-21 06:44:16

标签: scala apache-spark dataframe apache-spark-sql

我有火花数据帧mainDFdeltaDF两者都有匹配的架构。

mainDF的内容如下:

id | name | age
1  | abc  | 23
2  | xyz  | 34
3  | pqr  | 45

deltaDF的内容如下:

id | name | age
1  | lmn  | 56
4  | efg  | 37

我想根据deltaDF的值将mainDFid合并。因此,如果id中已存在mainDF,则应更新记录,如果id不存在,则应添加新记录。因此,结果数据框应如下所示:

id | name | age
1  | lmn  | 56
2  | xyz  | 34
3  | pqr  | 45
4  | efg  | 37

这是我目前的代码,它正在运行:

  val updatedDF = mainDF.as("main").join(deltaDF.as("delta"),$"main.id" === $"delta.id","inner").select($"main.id",$"main.name",$"main.age")
 mainDF= mainDF.except(updateDF).unionAll(deltaDF)

但是在这里我需要在select函数中再次明确地提供列表列,这对我来说是一种开销。还有其他更好/更清洁的方法来实现同样的目标吗?

3 个答案:

答案 0 :(得分:2)

如果您不想明确提供列的列表,可以映射原始DF的列,例如:

.select(mainDF.columns.map(c => $"main.$c" as c): _*)

顺便说一下,你可以在union之后没有join的情况下执行此操作:您可以使用outer加入来获取两个DF中都不存在的记录,然后使用{ {1}}到"选择"非空值更喜欢coalesce的值。所以完整的解决方案就像:

deltaDF

答案 1 :(得分:2)

您可以使用dropDuplicates并指定您不希望重复的列来实现此目的。

这是一个有效的代码:

 val a = (1,"lmn",56)::(2,"abc",23)::(3,"pqr",45)::Nil
 val b = (1,"opq",12)::(5,"dfg",78)::Nil

 val df1 = sc.parallelize(a).toDF
 val df2 = sc.parallelize(b).toDF

 df1.unionAll(df2).dropDuplicates("_1"::Nil).show()

+---+---+---+
| _1| _2| _3|
+---+---+---+
|  1|lmn| 56|
|  2|abc| 23|
|  3|pqr| 45|
|  5|dfg| 78|
+---+---+---+

答案 2 :(得分:0)

另一种方法:pyspark实施

updatedDF = mainDF.alias(“main”).join(deltaDF.alias(“delta”), main.id == delta.id,"left")
upsertDF = updatedDF.where(“main.id IS not null").select("main.*")
unchangedDF = updatedDF.where(“main.id IS NULL”).select("delta.*")
finalDF = upsertDF.union(unchangedDF)