Получение общего количества сеансов для пар, имеющих совместные сеансы, довольно просто. Вы можете достичь этого, присоединив DataFrame к себе на session_id
и отфильтровав строки, где product
s одинаковы.
Затем вы группируете по парам product
и подсчитываете различные session_id
с.
import pyspark.sql.functions as f
rows_df.alias("l").join(rows_df.alias("r"), on="session_id", how="inner")\
.where("l.product != r.product")\
.groupBy(f.col("l.product").alias("product_a"), f.col("r.product").alias("product_b"))\
.agg(f.countDistinct("session_id").alias("num_join_sessions"))\
.show()
#+---------+---------+-----------------+
#|product_a|product_b|num_join_sessions|
#+---------+---------+-----------------+
#| A| C| 1|
#| C| A| 1|
#| B| A| 2|
#| A| B| 2|
#+---------+---------+-----------------+
(Примечание: если вы хотите использовать ТОЛЬКО уникальные пары продуктов, измените значение !=
на <
в функции where
).
Сложность в том, что вам также нужны пары, у которых нет совместных сеансов. Это может быть выполнено, но оно не будет эффективным, потому что вам нужно будет получать декартово произведение каждой пары продуктов.
Тем не менее, вот один подход:
Начните с вышеизложенного и ПРАВИЛЬНО объедините декартово произведение пар различных товаров.
rows_df.alias("l").join(rows_df.alias("r"), on="session_id", how="inner")\
.where("l.product != r.product")\
.groupBy(f.col("l.product").alias("product_a"), f.col("r.product").alias("product_b"))\
.agg(f.countDistinct("session_id").alias("num_join_sessions"))\
.join(
rows_df.selectExpr("product AS product_a").distinct().crossJoin(
rows_df.selectExpr("product AS product_b").distinct()
).where("product_a != product_b").alias("pairs"),
on=["product_a", "product_b"],
how="right"
)\
.fillna(0)\
.sort("product_a", "product_b")\
.show()
#+---------+---------+-----------------+
#|product_a|product_b|num_join_sessions|
#+---------+---------+-----------------+
#| A| B| 2|
#| A| C| 1|
#| B| A| 2|
#| B| C| 0|
#| C| A| 1|
#| C| B| 0|
#+---------+---------+-----------------+
Примечание: sort
не требуется, но я включил его, чтобы соответствовать порядку желаемого выхода.