pyspark 数据帧中的完全外连接

Posted

技术标签:

【中文标题】pyspark 数据帧中的完全外连接【英文标题】:Full outer join in pyspark data frames 【发布时间】:2018-05-08 18:39:55 【问题描述】:

我在pyspark 中创建了两个数据框,如下所示。在这些data frames 中,我有列id。我想对这两个数据帧执行full outer join

valuesA = [('Pirate',1),('Monkey',2),('Ninja',3),('Spaghetti',4)]
a = sqlContext.createDataFrame(valuesA,['name','id'])

a.show()
+---------+---+
|     name| id|
+---------+---+
|   Pirate|  1|
|   Monkey|  2|
|    Ninja|  3|
|Spaghetti|  4|
+---------+---+


valuesB = [('dave',1),('Thor',2),('face',3), ('test',5)]
b = sqlContext.createDataFrame(valuesB,['Movie','id'])

b.show()
+-----+---+
|Movie| id|
+-----+---+
| dave|  1|
| Thor|  2|
| face|  3|
| test|  5|
+-----+---+


full_outer_join = a.join(b, a.id == b.id,how='full')
full_outer_join.show()

+---------+----+-----+----+
|     name|  id|Movie|  id|
+---------+----+-----+----+
|   Pirate|   1| dave|   1|
|   Monkey|   2| Thor|   2|
|    Ninja|   3| face|   3|
|Spaghetti|   4| null|null|
|     null|null| test|   5|
+---------+----+-----+----+

当我执行full_outer_join 时,我希望得到如下结果

+---------+-----+----+
|     name|Movie|  id|
+---------+-----+----+
|   Pirate| dave|   1|
|   Monkey| Thor|   2|
|    Ninja| face|   3|
|Spaghetti| null|   4|
|     null| test|   5|
+---------+-----+----+

我已经完成了下面的操作,但得到了一些不同的结果

full_outer_join = a.join(b, a.id == b.id,how='full').select(a.id, a.name, b.Movie)
full_outer_join.show()
+---------+----+-----+
|     name|  id|Movie|
+---------+----+-----+
|   Pirate|   1| dave|
|   Monkey|   2| Thor|
|    Ninja|   3| face|
|Spaghetti|   4| null|
|     null|null| test|
+---------+----+-----+

如您所见,我的result data frame 中缺少Id 5

我怎样才能实现我想要的?

【问题讨论】:

【参考方案1】:

由于连接列具有相同的名称,您可以将连接列指定为列表:

a.join(b, ['id'], how='full').show()
+---+---------+-----+
| id|     name|Movie|
+---+---------+-----+
|  5|     null| test|
|  1|   Pirate| dave|
|  3|    Ninja| face|
|  2|   Monkey| Thor|
|  4|Spaghetti| null|
+---+---------+-----+

coalesce 两个id 列:

import pyspark.sql.functions as F
a.join(b, a.id == b.id, how='full').select(
    F.coalesce(a.id, b.id).alias('id'), a.name, b.Movie
).show()
+---+---------+-----+
| id|     name|Movie|
+---+---------+-----+
|  5|     null| test|
|  1|   Pirate| dave|
|  3|    Ninja| face|
|  2|   Monkey| Thor|
|  4|Spaghetti| null|
+---+---------+-----+

【讨论】:

鉴于此,如果您有 2 个具有 2 个不同列名的表,并且不希望在 select 语句中提及所有列名。我使用以下方法实现了它:full_outer_join = a.join(b, a.a_id == b.b_id, how='full').withColumn("id", F.coalesce(a.a_id, b.b_id)).drop("a_id", "b_id") 【参考方案2】:

您可以重命名数据框 b 中的列 ID 并稍后删除,或者在连接条件中使用列表。

a.join(b, ['id'], how='full')

输出:

+---+---------+-----+
|id |name     |Movie|
+---+---------+-----+
|1  |Pirate   |dave |
|3  |Ninja    |face |
|5  |null     |test |
|4  |Spaghetti|null |
|2  |Monkey   |Thor |
+---+---------+-----+

【讨论】:

以上是关于pyspark 数据帧中的完全外连接的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 映射 2 个数据帧中的值和外连接 + 聚合值

如何使用 PySpark 对两个 RDD 进行完全外连接?

Pyspark:内部连接两个 pyspark 数据帧并从第一个数据帧中选择所有列,从第二个数据帧中选择几列

如何在熊猫数据框中执行左外连接?

django中的完全外连接

左外连接和右外连接的区别