Spark Dataframes的subtractByKey?

时间:2016-08-25 00:20:23

标签: apache-spark pyspark pyspark-sql

假设我有两个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。但我不认为这也特别干净!

有什么好主意吗?

1 个答案:

答案 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()