排除对称结果的 PySpark 交叉连接
PySpark cross join excluding symmetric results
我有一个 Spark 数据框:
> df
+---+
| id|
+---+
| a|
+---+
| b|
+---+
| c|
+---+
我想获得 id
列的所有对,所以我需要交叉连接数据框本身。但我想排除对称结果(在我的例子中 a,b == b,a
,等等)。
如果我应用 df.withColumnRenamed('id', 'id1').crossJoin(df.withColumnRenamed('id', 'id2')).show()
我得到以下输出:
+---+---+
|id1|id2|
+---+---+
| a| a|
| a| b|
| a| c|
| b| a|
| b| b|
| b| c|
| c| a|
| c| b|
| c| c|
+---+---+
但期望的输出是:
+---+---+
|id1|id2|
+---+---+
| a| a|
| a| b|
| a| c|
| b| b|
| b| c|
| c| c|
+---+---+
在 SQL 中,我可以使用这样的方法实现这样的结果:
select df1.*, df2.*
from df df1 join df df2
on df1.id < df2.id
如何使用 PySpark 实现此功能?
您可以使用范围连接
df.withColumnRenamed('id', 'id1').createOrReplaceTempView("df1")
df.withColumnRenamed('id', 'id2').createOrReplaceTempView("df2")
spark.sql(
"""SELECT *
FROM df1, df2
WHERE df1.id1 = df2.id2
OR df1.id1 < df2.id2""").show()
或者您可以按自己的方式进行交叉连接(这是一个非常昂贵的操作),从 id1 和 id2 创建数组并对其进行排序,对数组进行排序并使用它来删除重复项。我不建议交叉连接。
df.withColumnRenamed('id', 'id1').crossJoin(df.withColumnRenamed('id', 'id2')).withColumn('filter', array_sort(array('id1','id2'))).dropDuplicates(['filter']).drop('filter').show()
+---+---+
|id1|id2|
+---+---+
| a| a|
| a| b|
| a| c|
| b| b|
| b| c|
| c| c|
+---+---+
我有一个 Spark 数据框:
> df
+---+
| id|
+---+
| a|
+---+
| b|
+---+
| c|
+---+
我想获得 id
列的所有对,所以我需要交叉连接数据框本身。但我想排除对称结果(在我的例子中 a,b == b,a
,等等)。
如果我应用 df.withColumnRenamed('id', 'id1').crossJoin(df.withColumnRenamed('id', 'id2')).show()
我得到以下输出:
+---+---+
|id1|id2|
+---+---+
| a| a|
| a| b|
| a| c|
| b| a|
| b| b|
| b| c|
| c| a|
| c| b|
| c| c|
+---+---+
但期望的输出是:
+---+---+
|id1|id2|
+---+---+
| a| a|
| a| b|
| a| c|
| b| b|
| b| c|
| c| c|
+---+---+
在 SQL 中,我可以使用这样的方法实现这样的结果:
select df1.*, df2.*
from df df1 join df df2
on df1.id < df2.id
如何使用 PySpark 实现此功能?
您可以使用范围连接
df.withColumnRenamed('id', 'id1').createOrReplaceTempView("df1")
df.withColumnRenamed('id', 'id2').createOrReplaceTempView("df2")
spark.sql(
"""SELECT *
FROM df1, df2
WHERE df1.id1 = df2.id2
OR df1.id1 < df2.id2""").show()
或者您可以按自己的方式进行交叉连接(这是一个非常昂贵的操作),从 id1 和 id2 创建数组并对其进行排序,对数组进行排序并使用它来删除重复项。我不建议交叉连接。
df.withColumnRenamed('id', 'id1').crossJoin(df.withColumnRenamed('id', 'id2')).withColumn('filter', array_sort(array('id1','id2'))).dropDuplicates(['filter']).drop('filter').show()
+---+---+
|id1|id2|
+---+---+
| a| a|
| a| b|
| a| c|
| b| b|
| b| c|
| c| c|
+---+---+