PySpark-比较数据框

时间:2018-08-13 14:31:16

标签: python apache-spark pyspark apache-spark-sql pyspark-sql

我是PySpark的新手,因此,如果这有点简单,我很抱歉,我发现其他问题可以比较数据帧,但不是这样的,因此我不认为它是重复的。 我正在尝试比较结构相似的两个日期框架。 “名称”将是唯一的,但计数可能会有所不同。

因此,如果计数不同,我希望它产生一个数据框或python字典。就像下面一样。关于如何实现这样的目标有什么想法吗?

DF1

+-------+---------+
|name   | count_1 |
+-------+---------+
|  Alice|   1500  |
|    Bob|   1000  |
|Charlie|   150   |
| Dexter|   100   |
+-------+---------+

DF2

+-------+---------+
|name   | count_2 |
+-------+---------+
|  Alice|   1500  |
|    Bob|   200   |
|Charlie|   150   |
| Dexter|   10    |
+-------+---------+

产生结果:

不匹配

+-------+-------------+--------------+
|name   | df1_count   | df2_count    |
+-------+-------------+--------------+
|    Bob|   1000      |    200       |
| Dexter|   100       |     10       |
+-------+-------------+--------------+

匹配

+-------+-------------+--------------+
|name   | df1_count   | df2_count    |
+-------+-------------+--------------+
|  Alice|   1500      |   1500       |
|Charlie|   150       |    150       |
+-------+-------------+--------------+

5 个答案:

答案 0 :(得分:1)

对于小型DataFrame比较,可以使用chispa库。在测试套件中执行DataFrame比较时,这特别有用。对于大型数据集,使用联接的公认答案是最好的方法。

在此示例中,chispa.assert_df_equality(df1, df2)将输出以下错误消息:

enter image description here

不匹配的行为红色,匹配的行为蓝色。 This post有更多有关测试PySpark代码的信息。

有一个很酷的库名为deequ,可用于“数据单元测试”,但是我不确定是否有PySpark实现。

答案 1 :(得分:0)

因此,我创建了第三个DataFrame,将DataFrame1和DataFrame2连接起来,然后按计数字段进行过滤以检查它们是否相等:

不匹配:

df3 = df1.join(df2, [df1.name == df2.name] , how = 'inner' )
df3.filter(df3.df1_count != df3.df2_count).show()

匹配:

df3 = df1.join(df2, [df1.name == df2.name] , how = 'inner' )
df3.filter(df3.df1_count == df3.df2_count).show()

希望这对某人有用

答案 2 :(得分:0)

您可以在每个数据框的顶部创建一个临时视图,并编写Spark SQL查询以进行连接。直接数据框联接和Spark SQL联接是可以在此处探讨的两个选项。 SQL更直观,因此对于新手来说可能很容易。

答案 3 :(得分:0)

MATCH

Df1.join(Df2,Df1.col(“name”) === Df2.col(“name”) && Df1.col(“count_1”) === Df2.col(“count_2”),”inner”).drop(Df2.col(“name”)).show

MISMATCH

Df1.join(Df2,Df1.col(“name”) === Df2.col(“name”) && Df1.col(“count_1”) === Df2.col(“count_2”),”leftanti”).as(“Df3”).join(Df2,Df2.col(“name”) === col(“Df3.name”),”inner”).drop(Df2.col(“name”)).show

答案 4 :(得分:0)

简单的方法是使用spark-extension包中的diff转换:

from gresearch.spark.diff import *

left = spark.createDataFrame([("Alice", 1500), ("Bob", 1000), ("Charlie", 150), ("Dexter", 100)], ["name", "count"])
right = spark.createDataFrame([("Alice", 1500), ("Bob", 200), ("Charlie", 150), ("Dexter", 10)], ["name", "count"])

diff = left.diff(right, 'name')
diff.show()
+----+-------+----------+-----------+                                           
|diff|   name|left_count|right_count|
+----+-------+----------+-----------+
|   N|  Alice|      1500|       1500|
|   C|    Bob|      1000|        200|
|   N|Charlie|       150|        150|
|   C| Dexter|       100|         10|
+----+-------+----------+-----------+

这显示您在一个DataFrame中不匹配(C)和匹配(N)。

当然,您可以进行过滤以获取不匹配项和仅匹配项:

diff.where(diff['diff'] == 'C').show()
+----+------+----------+-----------+                                            
|diff|  name|left_count|right_count|
+----+------+----------+-----------+
|   C|   Bob|      1000|        200|
|   C|Dexter|       100|         10|
+----+------+----------+-----------+

diff.where(diff['diff'] == 'N').show()
+----+-------+----------+-----------+                                           
|diff|   name|left_count|right_count|
+----+-------+----------+-----------+
|   N|  Alice|      1500|       1500|
|   N|Charlie|       150|        150|
+----+-------+----------+-----------+

虽然这是一个简单的示例,但是当涉及到广泛的架构,插入,删除和空值时,差异化DataFrame会变得复杂。