我正在研究一些单元测试Spark代码,这些代码应该能够在两个数据帧(原始存储桶和指定存储桶)之间产生差异。两个数据帧(存储桶)都相同,并且我们希望在将文件从原始文件复制到策展文件后执行此代码以捕获可能的更改。 。我知道我可以使用except
函数,如下所示:
val difference =CuratedDataFrame.union(RawDataFrame).except(CuratedDataFrame.intersect(RawDataFrame))
+-----------+-------+-------------+---------+---------------+
|record |pid |feetype |freq |default |
+-----------+-------+-------------+---------+---------------+
| 1| 45| FAC| Y| T|
| 1| 45| FAC| Y| TTY|
| 1| 47| FAC| R| M|
| 1| 99| FAC| R| M|
+-----------+-------+-------------+---------+---------------+
except函数返回整行,但我想要的输出如下:
+-----------+-------+-------------+---------+---------------+
|record |pid |feetype |freq |default |
+-----------+-------+-------------+---------+---------------+
| null|[47,99]| null| null| null |
| null| null| null| null| [T, TTY]|
+----------+-----------+-------+-------------+---------+-----
这意味着如果列中有更改,则应显示,如果没有更改,则应将其隐藏或为Null。
为此,我使用以下方法:
val mapDiffs=(name: String) => when($"l.$name" === $"r.$name", null )
.otherwise(array($"l.$name", $"r.$name")).as(name)
val result = difference.as("l")
.join(RawDataFrame.as("r"), $"l.primaryKey" === $"r.primaryKey","inner")
.select($"l.primaryKey" :: cols.map(mapDiffs): _*)
以上方法要求主键能够连接两个数据框并逐行比较它们。没有一个数据框具有主键,因此我不得不结合一些列来指定一个主键:
+-----------+-------+-------------+---------+---------------+----------+
|record |pid |feetype |freq |default |primaryKey|
+-----------+-------+-------------+---------+---------------+----------+
| 1| 40| FAC| A| N| FAC40A|
| 1| 45| FAC| Y| T| FAC45Y|
| 1| 47| FAC| R| M| FAC47R|
+-----------+-------+-------------+---------+---------------+----------+
问题是,如果目标存储桶中发生任何更改,则主键将因此更改,因此无法比较两个数据帧。