Python 具有GroupedData的pyspark笛卡尔积(交叉连接)
我有一个Pypark数据框Python 具有GroupedData的pyspark笛卡尔积(交叉连接),python,pyspark,user-defined-functions,cartesian-product,cross-join,Python,Pyspark,User Defined Functions,Cartesian Product,Cross Join,我有一个Pypark数据框 +---+----+----+ |key|col1|col2| +---+----+----+ |a |5.4 | 1| |a |6.5 | 2| |b |7.5 | 3| |b |4.5 | 4| |c |6.4 | 1| +--------+----+ 我想做笛卡尔积,但不是在每一行之间,而是在每一个groupby(“key”)之间,然后对其应用一些python函数。 也就是说,先进行groupby(“键”),然后对每个Groupe
+---+----+----+
|key|col1|col2|
+---+----+----+
|a |5.4 | 1|
|a |6.5 | 2|
|b |7.5 | 3|
|b |4.5 | 4|
|c |6.4 | 1|
+--------+----+
我想做笛卡尔积,但不是在每一行之间,而是在每一个groupby(“key”)之间,然后对其应用一些python函数。
也就是说,先进行groupby(“键”),然后对每个GroupedData(a与b、a与c、b与c)进行笛卡尔积(交叉连接)
预期输出应为具有预定义方案的数据帧
schema = StructType([
StructField("some_col_1", StringType(), False),
StructField("some_col_2", StringType(), False)
])
因此,自定义函数应该类似于:
def custom_func(df_1: pd.DataFrame, df_2: pd.DataFrame) -> pd.DataFrame
或者(可以是spark数据帧而不是python数据帧):
我尝试了两个groupby,然后使用cogroup:
group1 = df.groupby("key")
group2 = df.groupby("key")
res = group1.cogroup(group2).applyInPandas(custom_func, schema)
但它不是笛卡尔积。
我尝试使用交叉连接,但它只应用数据帧。如何将其应用于GroupedData?
有什么办法做这件事吗
编辑:
添加图片以更好地解释问题
作为第一步,您可以执行交叉连接并过滤键不同的行:
df2 = df.alias('a').join(
df.alias('b'),
F.expr('a.key < b.key')
).toDF(
*[c+'_a' for c in df.columns],
*[c+'_b' for c in df.columns])
df2.show()
+-----+------+------+-----+------+------+
|key_a|col1_a|col2_a|key_b|col1_b|col2_b|
+-----+------+------+-----+------+------+
| a| 5.4| 1| b| 7.5| 3|
| a| 5.4| 1| b| 4.5| 4|
| a| 5.4| 1| c| 6.4| 1|
| a| 6.5| 2| b| 7.5| 3|
| a| 6.5| 2| b| 4.5| 4|
| a| 6.5| 2| c| 6.4| 1|
| b| 7.5| 3| c| 6.4| 1|
| b| 4.5| 4| c| 6.4| 1|
+-----+------+------+-----+------+------+
你的预期产量是多少?您将如何在这两个组上应用自定义函数?你能提供更多细节吗?@mck这是一个虚构的例子,我的自定义函数很复杂,所以我没有把它包括在问题中。从每个交叉连接中,我需要返回一个数据帧(使用预定义的方案)。不确定还需要提供哪些其他细节“^^请阅读如何创建ok,阅读它,但仍然缺少哪些信息?我回答什么是预期输出,如何在两个组上应用自定义函数是问题的一部分,使用cogroup是一个选项,但任何其他方法都可以工作。您没有提供预期输出,也没有提供函数。问题是我不需要在每一行上都执行自定义函数,函数需要获得整个GroupedData(参见我添加的图片)。然后您可以在
a.key
和b.key
上进行分组,并对您现在要使用的每个组应用您的函数:res=group1.cogroup(group2.applyinpandes(自定义函数,模式),对吗?感觉像是一个效率不高的解决方案。实际上,我的数据集并不小,我有大约300个不同的键和100多个列。你能想出另一种解决方案吗?我认为最好将数据分组,然后尽可能进行笛卡尔积。不,只需通过a.key和b.key进行简单分组,然后应用Pandasi:df2=df.alias('a').join(df.alias('b')、F.expr('a.keydf2 = df.alias('a').join(
df.alias('b'),
F.expr('a.key < b.key')
).toDF(
*[c+'_a' for c in df.columns],
*[c+'_b' for c in df.columns])
df2.show()
+-----+------+------+-----+------+------+
|key_a|col1_a|col2_a|key_b|col1_b|col2_b|
+-----+------+------+-----+------+------+
| a| 5.4| 1| b| 7.5| 3|
| a| 5.4| 1| b| 4.5| 4|
| a| 5.4| 1| c| 6.4| 1|
| a| 6.5| 2| b| 7.5| 3|
| a| 6.5| 2| b| 4.5| 4|
| a| 6.5| 2| c| 6.4| 1|
| b| 7.5| 3| c| 6.4| 1|
| b| 4.5| 4| c| 6.4| 1|
+-----+------+------+-----+------+------+
df2.groupBy('key_a', 'key_b').applyInPandas(...)