我有火花数据帧mainDF
和deltaDF
两者都有匹配的架构。
mainDF的内容如下:
id | name | age
1 | abc | 23
2 | xyz | 34
3 | pqr | 45
deltaDF
的内容如下:
id | name | age
1 | lmn | 56
4 | efg | 37
我想根据deltaDF
的值将mainDF
与id
合并。因此,如果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函数中再次明确地提供列表列,这对我来说是一种开销。还有其他更好/更清洁的方法来实现同样的目标吗?
答案 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)