假设我有两个DataFrame:
headers = ["id", "info"]
a = sc.parallelize([(1, "info1"), (2, "info2"), (3, "info3")]).toDF(headers)
b = sc.parallelize([(2, "info2new")]).toDF(headers)
我想从a
获取文件,但会覆盖a
中显示的b
中的那些行。所以期望的输出是
+---+--------+
| id| info|
+---+--------+
| 1| info1|
| 2|info2new|
| 3| info3|
+---+--------+
现在,我可以将我的DataFrame转换为RDD,并使用subtractByKey
,但这会强制我转换为RDD,映射到(键,值)元组,然后转换回DataFrame。 MEH。
我环顾了saw the functions except
and subtract
for Spark DataFrames,但这些要求行完全重复,而我的不是。
我现在考虑这样做的方式是这样的:
a1 = a.select(*(col(x).alias(x + '_old') for x in a.columns))
b1 = b.select(*(col(x).alias(x + '_new') for x in b.columns))
x = a1.join(b1, a1['id_old'] == b1['id_new"], "outer")
然后我将x注册为tempTable并编写一个SQL查询,该查询将返回旧数据,除非新数据不为null。但我不认为这也特别干净!
有什么好主意吗?
答案 0 :(得分:0)
不确定最好的方法,但您可以使用left outer
和一些清洁工具join
UDF
。
<强> Scala的:强>
// UDF to choose info value
val newInfo = udf[String,String,String]((infoA,infoB) => {
if (infoB == null)
infoA
else
infoB
})
// join -> add col("newInfo") -> drop info cols -> rename "newInfo"
a.join(b, Seq("id"), "left_outer")
.withColumn("newInfo", newInfo(a("info"), b("info")))
.drop(a("info"))
.drop(b("info"))
.withColumnRenamed("newInfo", "info")
.show()