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 数据帧中的完全外连接的主要内容,如果未能解决你的问题,请参考以下文章