比较pyspark中的两个数据集

时间:2020-02-12 14:15:57

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

我有2个数据集。

示例数据集1:

id     |   model |   first_name   |      last_name
-----------------------------------------------------------
1234   |   32    |    456765      |   [456700,987565]
-----------------------------------------------------------
4539   |   20    |    123211      |   [893456,123456]
-----------------------------------------------------------

有时first_name和last_name列之一为空。

示例数据集2:

number  |  matricule   | name       |    model
----------------------------------------------------------
AA      |  0009        |  456765    |     32
----------------------------------------------------------
AA      |  0009        |  893456    |     32
----------------------------------------------------------
AA      |  0009        |  456700    |     32
----------------------------------------------------------
AA      |  0008        |  456700    |     32
----------------------------------------------------------
AA      |  0008        |  987565    |     32

对于一个matricule,我们可以找到更多的namemodel,就像上面的示例一样。 我应该怎么做:

对于数据集1中的每一行,我采用3列:模型,first_name和last_name,并在数据集2中查找它们(如果存在/根据矩阵元素匹配)。

我应该比较:

  • 每个模型的模型==>如果模型(数据集1)存在于模型(数据集2)==>匹配中

  • 如果名字中存在名字==>则不匹配。如果名字中不存在first_name ==>匹配

  • 如果在name ==>匹配项中存在last_name。当我有两个last_name值时,两者都应存在于要匹配的数据集2的名称中。

示例:

数据集1中的行1为:

id     |   model |   first_name   |      last_name
------------------------------------------------------
1234   |   32    |    456765      |   [456700,987565]

对于数据集2中的矩阵0009,我有:

number  |  matricule   | name       |    model
----------------------------------------------------------
AA      |  0009        |  456765    |     32
----------------------------------------------------------
AA      |  0009        |  893456    |     32
----------------------------------------------------------
AA      |  0009        |  456700    |     32

所以:

当材料= 0009 ==>不匹配时,数据集2的名称中存在

first_name(456765)

姓氏,仅存在456700 ==>不匹配

数据集2的模型中存在

模型(32)==>匹配

所以我跳过了矩阵0009。然后将数据集1中的第二行与矩阵0008的元素进行比较。

对于数据集2中的矩阵0008,我有:

----------------------------------------------------------
AA      |  0008        |  456700    |     32
----------------------------------------------------------
AA      |  0008        |  987565    |     32

我们总是在数据集1的第一行中

矩阵= 0008 ==>匹配时,数据集2的名称中不存在

first_name(456765)

last_name,当矩阵= 0008,==>匹配时,两个值都存在于数据集2的名称中

当矩阵= 0008 ==>匹配时,数据集2的模型中存在

模型

找到所有匹配项后,我将创建一个包含以下内容的新数据集:

number | id     |  matricule
-----------------------------------
AA     | 1234   | 0008
-----------------------------------

我希望我很清楚。有人可以帮我。

1 个答案:

答案 0 :(得分:1)

您可以在匹配条件下使用join。

首先,您可以将第二个DataFrame分组,并将name列收集到一个列表中:

df2 = df2.groupBy("number", "model", "matricule").agg(collect_list("name").alias("names"))
f2.show(truncate=False)

#+------+-----+---------+------------------------+
#|number|model|matricule|names                   |
#+------+-----+---------+------------------------+
#|AA    |32   |0009     |[456765, 893456, 456700]|
#|AA    |32   |0008     |[456700, 987565]        |
#+------+-----+---------+------------------------+

现在,加入df1df2。对于条件1和2,检查起来很简单。 对于第三个,您可以使用Spark 2.4+提供的array_exceptlast_name列中的元素不应该包含在names中,反之亦然):

join_condition = (col("df1.model") == col("df2.model")) \
                 & ~expr("array_contains(df2.names, df1.first_name)") \
                 & (size(expr("array_except(df2.names, df1.last_name)")) == lit(0)) \
                 & (size(expr("array_except(df1.last_name, df2.names)")) == lit(0))


df_result = df1.alias("df1").join(df2.alias("df2"), join_condition)

最后,从联接结果中选择所需的列:

df_result.select("number", "id", "matricule").show(truncate=False)

#+------+----+---------+
#|number|id  |matricule|
#+------+----+---------+
#|AA    |1234|0008     |
#+------+----+---------+
相关问题