我知道这个问题在这里也被问到过,但是没有人提出当reduce中的一个或两个数据框为空的情况。在这种情况下,执行内部连接的最终结果将始终为空
如果我有:
dfList = List(
+--------+-------------+ +--------+-------------+ +--------+--------+ +--------+--------+
| ID | A | ID | B | | ID | C | | ID | D |
+--------+-------------+ +--------+-------------+ +--------+--------+ +--------+--------+
| 9574| F| | 9574| 005912| | 9574| 2016022| | 9574| VD|
| 9576| F| | 9576| 005912| | 9576| 2016022| | 9576| VD|
| 9578| F| | 9578| 005912| | 9578| 2016022| | 9578| VD|
| 9580| F| | 9580| 005912| | 9580| 2016022| | 9580| VD|
| 9582| F| | 9582| 005912| | 9582| 2016022| | 9582| VD|
+--------+-------------+, +--------+-------------+,+--------+--------+,+--------+--------+
)
,我想把这个列表减少到一个数据帧,我可以很容易地做到:
listDataFrames.reduce(
(df1, df2) =>
df1.join(df2, Seq("ID")).localCheckpoint(true)
)
无论连接是什么(内部连接、左连接还是右连接),如果前两个数据框中有一个为空,则最终结果将为空。
一种可能是:
listDataFrames.filter(!_.rdd.isEmpty())
,但它需要很多时间,所以它在性能方面不是很好。你有什么建议吗?
如果你是在Spark 3.1上,你实际上可以使用unionByName &集团通过
df1.unionByName(df2, allowMissingColumns=True).grouby("ID","A","B","C","D")
在其他版本中,你可以做类似的事情,但我还没有测试过性能:(并且有一个问题,它只适用于数字字段,很可能你必须来回做一些转换。)
df2.select(
df2.ID,
df2.B.alias("col1"),
f.lit("B").alias("table"))
.union(
df1.select(
df1.ID,
df1.A.alias("col1"),
f.lit("A")))
.groupBy("ID")
.pivot("table")
.max("col1")
.show()